SQL计数未知列数的空单元格

时间:2016-09-05 09:14:08

标签: sql sql-server

我有一个包含未知列数(以及未知列名称)的表,其中包含不同类型的数据(可以是从bit到nvarchar或datetime的任何内容),如下所示:

ID   | Col2 | Col3 | Customer |  ..(etc)..
1    | NULL |  0   |  CustA   |    
2    | valA |  1   |  NULL    |
3    | valB | NULL |  (empty) |

我需要一个查询来计算每列上的所有NULL和空单元格,并输出如下结果:

Column_Name  |  No_Of_Empty_And_Null_Cells | 
   Col2      |             1               |
   Col3      |             1               |
 Customer    |             2               |
 (etc...)    |                             |

我知道我必须使用动态查询和UNPIVOT,但我的SQL知识远不及那个!

How to count all NULL values in a table?似乎不起作用,因为它与MySQL相关,而不是MS SQL

3 个答案:

答案 0 :(得分:3)

您可以尝试使用此动态SQL代码:

DECLARE @schema VARCHAR(100)='dbo';
DECLARE @tableName VARCHAR(100)='SomeTable';

DECLARE @DynamicSelect VARCHAR(MAX)=
(
  STUFF((SELECT 'UNION SELECT ''' + COLUMN_NAME + ''' AS COLUMN_NAME' + 
         ', (SELECT COUNT(*) FROM ' + @schema + '.' + @tableName + ' WHERE [' + COLUMN_NAME + '] IS NULL) AS No_Of_Null_Cells '
         FROM INFORMATION_SCHEMA.COLUMNS AS c
         WHERE c.TABLE_SCHEMA=@schema AND c.TABLE_NAME=@tableName AND c.IS_NULLABLE='YES'
         FOR XML PATH('')
        ),1,6,'')
);
exec (@DynamicSelect)


DECLARE @DynamicSelect2 VARCHAR(MAX)=
(
  STUFF((SELECT 'UNION SELECT ''' + COLUMN_NAME + ''' AS COLUMN_NAME' + 
         ', (SELECT COUNT(*) FROM ' + @schema + '.' + @tableName + ' WHERE LTRIM(RTRIM([' + COLUMN_NAME + '])) ='''') AS No_Of_Empty_Cells '
         FROM INFORMATION_SCHEMA.COLUMNS AS c
         WHERE c.TABLE_SCHEMA=@schema AND c.TABLE_NAME=@tableName AND c.DATA_TYPE LIKE '%char%'
         FOR XML PATH('')
        ),1,6,'')
);
exec (@DynamicSelect2)

答案 1 :(得分:1)

这是一个从表中返回空值或空值的字段的方法 通过使用unpivot生成和执行动态查询 在SQL Server 2014上测试。

DECLARE @SchemaName SYSNAME = 'YourDatabase';
DECLARE @TableName SYSNAME = 'YourTable';

DECLARE @SQL NVARCHAR(MAX);

WITH COL AS (
    SELECT c.name
    FROM sys.objects o
    INNER JOIN sys.schemas s ON o.[schema_id] = s.[schema_id]
    INNER JOIN sys.columns c ON o.[object_id] = c.[object_id]
    WHERE o.[type] = 'U'
      AND s.name = @SchemaName 
      AND o.name = @TableName
      AND c.is_nullable = 1
)
SELECT @SQL = 'SELECT up.column_name, up.total_empty 
FROM (
 SELECT ' + CHAR(13) + STUFF((
    SELECT CHAR(13) + ', ' + QUOTENAME(name) + ' = SUM(IIF(LEN(RTRIM(' + QUOTENAME(name) + '))>0,0,1))'
    FROM COL
    FOR XML PATH(''), TYPE).value('.', 'VARCHAR(MAX)'), 1, 2, ' ') + '
 FROM ' + QUOTENAME(@SchemaName) + '.' + QUOTENAME(@TableName) + ') q
 UNPIVOT
 (total_empty for column_name in ('+
  STUFF((
    SELECT CHAR(13) + ', ' + QUOTENAME(name) FROM COL
    FOR XML PATH(''), TYPE).value('.', 'VARCHAR(MAX)'), 1, 2, ' ')
   +')
) up where up.total_empty > 0 order by up.column_name';

--SELECT @SQL;
EXEC sys.sp_executesql @SQL;

答案 2 :(得分:0)

编辑:这个答案适用于MySQL (最初没有仔细阅读)

this answer开始,我认为此结果会计算您的所有" null"细胞:

SET @db = 'your_database_name'; -- database
SET @tb = 'your_table_name'; -- 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 table_name=@tb and table_schema=@db;

-- we have to prepare some query from all columns of the table
SELECT group_concat(CONCAT('ASCII(',column_name,')')) into @x from information_schema.columns where table_name=@tb and table_schema=@db;
-- 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;