Mysql

從 information_schema 表中計算表的空值

  • October 10, 2016

有沒有辦法通過使用 information_Schema 表來計算列中的空值?例如:

SELECT table_name, table_rows
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA ='myschema'
and table_name='mytable'
and table_rows is null;

評論中的澄清:

我不能直接從表中獲取空值的數量,因為表很大,甚至沒有返回空值的計數,所以我認為information_schema這是從表中獲取空值的最佳選擇。但我不知道該怎麼做。有辦法嗎?

我有一個名為的表cal,其中一列包含空值。我只需要計算這些空值的數量。由於表很大,我無法使用select count(*) from tablename where column_name is null.

所以我需要一個查詢,它以某種方式計算來自 Information_Schema 的空值。

關於添加索引的建議:

但是我可以在列上添加索引column_type = mediumtext嗎?

MySQL 版本 5.1.73,表是 MyISAM。

不,您不能為此使用資訊模式。僅儲存表中行Information_schema.TABLES數的(近似)計數。不是值或空值的計數。

您應該在列上有一個索引,並使用簡單的查詢來代替:

-- if there isn't an index in place, add one:
alter table my_table
 add index (my_column_idx)
   (my_column) ;

select count(*)
from my_table
where my_column is null ;

但是如果我可以在列上添加索引column_type = mediumtext嗎?

嗯,不。

MySQL 版本 5.1.73,表是 MyISAM。

好的,現在我們有3個問題。

首先,您使用的是非常舊的、不受支持的 MySQL 版本。升級。至少到 5.5,如果不是到 5.6 或 5.7。這當然不是緊急的,只是部分與問題有關。即使在 5.7 中,我們仍然不能在 mediumtext 列上建立索引。

二、你用的是MyISAM嗎?還是在 2016 年?我猜它與 5.1 匹配得很好。無論如何,將表和應用程序轉換為使用 InnoDB。這也不緊急或與問題相關,但您會得到好處(交易、外鍵等)。但是不,即使使用 InnoDB,我們仍然不能在 mediumtext 列上建立索引。

那麼該怎麼辦?各種方式 - 不按任何特定順序拋出:

  • 在類似的東西上添加一個TINYINT計算的 ( ) 列並將其編入索引。需要升級到 5.7GENERATED``CASE WHEN column IS NOT NULL THEN 1 END
  • 按照前面的建議,添加一個TINYINT計算 ( VIRTUAL) 列,並將其編入索引。需要用 MariaDB 5.2 或 5.3 替換 MySQL 5.1(或升級到 5.5,然後用 MariaDB 5.5 或 10+ 替換)
  • 添加一TINYINT列(如計算的列),但填充值並由您的應用程序或觸發器保持正確。這不需要升級,但不建議在應用程序中強制執行完整性。不過考慮到 MyISAM 的使用,完整性似乎並不是一個優先事項。
  • 驅逐無效者!將表一分為二,僅將 mediumtext 列移動到第二個表(和主鍵)中。第二個表將只有列的非空值的行。然後你只需要計算該表的行數。您可以為此使用資訊架構!(或者只是計數,MyISAM 對整個表的計數速度很快。)不需要任何升級,但您的應用程序必須更改以處理新的、稍微改變的表結構。
  • 使用前綴索引(thnx 到@Michael-sqlbot的建議)。這根本不需要任何升級或修改:
-- a prefix index on the mediumtext column:
alter table my_table
 add index (my_column_1_idx)
   (my_column(1)) ;      -- one is enough

我沒有對此進行測試,但應該可以正常工作。它可能需要WHERE LEFT(my_column, 1) IS NULL在您的計數查詢中使用,但您可以測試。

如果您真的想NULL在所有表行中查找列,您可以做一些事情。

設想

你有一個mydb.mytable看起來像這樣的表

CREATE TABLE mytable
(
   id INT NOT NULL AUTO_INCREMENT,
   col1 VARCHAR(30) DEFAULT NULL,
   col2 VARCHAR(30) DEFAULT NULL,
   col3 VARCHAR(30) DEFAULT NULL,
   PRIMARY KEY (id)
);

你想知道有多少列mydb.mytableNULL. 讓我們選擇 col1。

SELECT
   COUNT(1) - COUNT(col) col1_null_count
FROM mydb.mytable;

現在,假設您想要所有列的計數

SELECT
   COUNT(1) - COUNT(col)id_null_count,
   COUNT(1) - COUNT(col) col1_null_count,
   COUNT(1) - COUNT(col) col2_null_count,
   COUNT(1) - COUNT(col) col3_null_count
FROM mydb.mytable;

當然,id_null_count將是零(0),因為id已定義NOT NULL

您的實際問題

為了動態確定這些計數,您需要INFORMATION_SCHEMA.COLUMNS

讓我們從一個查詢開始,該查詢告訴您哪些列允許NULL

SELECT column_name FROM information_schema.columns
WHERE table_schema='mydb'
AND table_name='mytable'
AND is_nullable='YES';

使用這個查詢,構造前面提到的計數查詢:

SET @DB='mydb';
SET @TB='mytable';
SET group_concat_max_len = 104857600;
SELECT CONCAT('SELECT ',select_columns,' FROM ',table_schema,'.',table_name)
INTO @sql FROM (SELECT GROUP_CONCAT(CONCAT('COUNT(1)-COUNT(',column_name,') ',
column_name,'_null_count')) select_columns FROM information_schema.columns
WHERE table_schema=@DB AND table_name=@TB
AND is_nullable='YES') A,information_schema.tables B
WHERE B.table_schema=@DB AND B.table_name=@TB;
PREPARE s FROM @sql; EXECUTE s\G DEALLOCATE PREPARE s;

這將執行以下操作

  • 收集所有可為空的列
  • 構造 SQL 來計算每一列NULL
  • 執行生成 SQL

您需要做的就是分配@DB@TB

請記住,這將使用單個查詢生成空列的計數,並且只執行一次全表掃描。

試一試 !!!

引用自:https://dba.stackexchange.com/questions/151855