2010-02-19 12 views
4

想知道,是否有任何快速的方法来计算MySQL表中的所有NULL值(来自所有列)?如何计算表中的所有NULL值?

感谢您的任何想法!

+0

有一种方法可以在MySQL中专门用SQL来实现。代码并不简单。看看我发布的解决方案。 – Pentium10 2010-02-19 12:48:43

回答

4

如果你想要这个由MySQL,没有列举所有的列专门做取看看这个解决方案。

在这种方法中,您不必通过硬编码来维护数据库列的数量。如果你的表模式将被修改,这个方法将会工作,并且不需要修改代码。

SET @db = 'testing'; -- database 
SET @tb = 'fuzzysearch'; -- table 
SET @x = ''; -- will hold the column names with ASCII method applied to retrieve the number of the first char 
SET @numcolumns = 0; -- will hold the number of columns in the table 

-- figure out how many columns we have 
SELECT count(*) into @numcolumns FROM information_schema.columns where [email protected] and [email protected]; 

-- we have to prepare some query from all columns of the table 
SELECT group_concat(CONCAT('ASCII(',column_name,')') SEPARATOR ",") into @x from information_schema.columns where [email protected] and [email protected]; 
-- after this query we have a variable separated with comma like 
-- ASCII(col1),ASCII(col2),ASCII(col3) 

-- we now generate a query to concat the columns using comma as separator (null values are omitted from concat) 
-- then figgure out how many times the comma is in that substring (this is done by using length(value)-length(replace(value,',','')) 
-- the number returned is how many non null columns we have in that column 
-- then we deduct the number from the known number of columns, calculated previously 
-- the +1 is added because there is no comma for single value 
SET @s = CONCAT('SELECT @numcolumns - (length(CONCAT_WS(\',\',', @x, '))-length(replace(CONCAT_WS(\',\',', @x, '),\',\',\'\')) + 1) FROM ',@db,'.',@tb,';'); 
PREPARE stmt FROM @s; 
EXECUTE stmt; 
-- after this execution we have returned for each row the number of null columns 
-- I will leave to you to add a sum() group call if you want to find the null values for the whole table 
DEALLOCATE PREPARE stmt; 

ASCII码是用来避免阅读,串联非常长柱没出息,也ASCII让我们安全的值,其中第一个字符是一个逗号(,)。

由于您正在使用报告,因此如果您将方法放在某个方法中,您可能会发现这有助于为每个表重用。

我试着让尽可能多的评论。

让我们在片分割上述紧凑的方式(逆向):

我想最终拥有这样

SELECT totalcolumns - notnullcolumns from table; -- to return null columns for each row 

查询虽然第一个是容易通过运行到calcule:

SELECT count(*) FROM information_schema.columns where [email protected] and [email protected]; 

第二个notnullcolumns是有点痛苦。 一块在MySQL中可用的功能检查后,我们检测到CONCAT_WS不CONCAT空值

所以运行这样的查询:

SELECT CONCAT_WS(",","First name",NULL,"Last Name"); 
returns: 'First name,Last Name' 

这是好事,我们就摆脱了空的枚举值。 但是,我们如何获得实际连接的列数?

那么,这是棘手。我们必须计算逗号+1来获得实际连接的列。

对于这一招,我们使用下面的SQL注释

select length(value)-length(replace(value,',','')) +1 from table 

好了,所以我们现在有串联的列数。

但是更难的部分是未来。

我们必须枚举CONCAT_WS()的所有值。
我们需要有这样的事情:

SELECT CONCAT_WS(",",col1,col2,col3,col4,col5); 

这是我们必须采取使用预处理语句的,因为我们必须从未知列准备动态SQL查询。我们不知道我们的桌子上有多少列。

因此,为此我们使用information_schema列表中的数据。我们需要传递表名,但也要传递数据库名,因为我们可能在不同的数据库中使用相同的表名。

我们需要返回COL1,COL2,COL3,COL4,COL5我们在CONCAT_WS “串”

因此,对于这一点,我们运行一个查询

SELECT group_concat(column_name SEPARATOR ",") into @x from information_schema.columns where [email protected] and [email protected]; 

还有一点要提的查询。当我们使用length()和replace()方法来找出连接了多少列时,我们必须确保这些值之间没有逗号。但是请注意,我们在数据库单元中可以有很长的值。对于这个技巧,我们使用方法ASCII('value'),它将返回第一个char的ASCII字符,它不能是逗号,并且对于空列将返回null。

这就是说,我们可以在上述综合解决方案中压缩所有这些。

+0

+1,虽然这有点难理解和维护 – Bozho 2010-02-19 13:02:59

+0

我增加了更多评论,并且这种方法不需要维护,如果他改变了表格模式,它将在没有代码改变的情况下工作。因此可以重用于其他原因。 – Pentium10 2010-02-19 13:48:44

+0

这真的很长很奇妙,解决了我的问题。这个函数的性能有多少?谢谢! – Nirmal 2010-02-20 03:22:30

4

喜欢的东西

select id 
     , sum (case when col1 is null then 1 else 0 end case) col1 
     , sum (case when col2 is null then 1 else 0 end case) col2 
     , sum (case when col3 is null then 1 else 0 end case) col3 
from contacts 
group by id 
+0

这涉及知道该表的列数,在大表上它不具有生产力。检查我的解决方案 – Pentium10 2010-02-19 12:57:16

+0

@Pentium - 你说的是真的,有办法解决这个问题。对于一次性查询,针对DESCRIBE的cut'n'pasted输出的简单正则表达式就足够了。或者可以从INFORMATION_SCHEMA生成查询。 – APC 2010-02-19 14:48:55

0

你应该这样不仅使用SQL,但是真正做的是在您的处置语言:

  1. 获取每个表的元数据 - 无论是使用DESCRIBE table,或使用db访问技术中的内置元数据功能

  2. 在每个柱的循环中创建以下类型的查询ñ。 (伪代码)

    int nulls = 0; 
    for (String colmnName : columNames) { 
        query = "SELECT COUNT(*) FROM tableName WHERE " + columnName + " IS NULL"; 
        Result result = executeQuery(query); 
        nulls += result.size(); 
    } 
    
+0

这将对每个列执行select查询,在大型表上可能有数百个查询。您可以获取每个表的元数据,并在SQL中使用它获取列中的空值,查看我的解决方案。 – Pentium10 2010-02-19 12:59:13

+0

在我看来,他正在做一次性统计数据,所以如果需要,他可以让它运行一整天:) – Bozho 2010-02-19 13:02:29

0

像这样的东西(替代COL_COUNT如适用):

select count(*) * COL_COUNT - count(col1) - count(col2) - ... - count(col_n) from table; 
+0

这涉及知道该表的列数,在大表上它不具有生产力。检查我的解决方案 – Pentium10 2010-02-19 13:00:03