從 information_schema 表中計算表的空值
有沒有辦法通過使用 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.mytable
是NULL
. 讓我們選擇 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
請記住,這將使用單個查詢生成空列的計數,並且只執行一次全表掃描。
試一試 !!!