2016-09-05 4 views
6

У меня есть таблица с неизвестным количеством столбцов (и имена неизвестных столбцов тоже) с различными типами данных (может быть что угодно: от бит до nvarchar или datetime), как показано ниже:SQL подсчет пустых ячеек в неизвестном количестве столбцов

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

+0

Возможный дубликат [Как посчитать все NULL значений в таблице?] (Http://stackoverflow.com/questions/2295318/how-to-count-all -null-values-in-a-table) – webmaster

+1

@webmaster, ваш * возможный дубликат * предназначен для 'MySQL', тогда как это работает против' SQL Server' – Shnugo

+0

Да, понимал поздно, большое спасибо. – webmaster

ответ

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 [email protected] AND [email protected] 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 [email protected] AND [email protected] AND c.DATA_TYPE LIKE '%char%' 
     FOR XML PATH('') 
     ),1,6,'') 
); 
exec (@DynamicSelect2) 
+0

Мне пришлось отредактировать второй динамический запрос, чтобы включить Nulls (так как мне нужны результаты в одном табличном формате), но он работал как шарм, спасибо! – espressionist

0

EDIT: Этот ответ для MySQL (не обязательно читать в первый)

От this answer, я думаю, что это результат будет считать всю вашу «нулевой» клетку:

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 [email protected] and [email protected]; 

-- 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 [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; 
+0

Спасибо за быстрый ответ, но ваш ответ относится к MySQL и, похоже, не работает в MSSQL – espressionist

+0

Ах, извините, я просто ошибочно оценил. Спасибо за предупреждение. – webmaster

1

Вот способ возврата полей с нулевыми или пустыми значениями из таблицы.
Визуализация и выполнение динамического запроса с помощью univot.
Испытано на 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; 
+0

Просто протестировал его сам, отлично работает с NULL, но мне нужно также включить пустые ячейки! – espressionist

+0

@espressionist Действительно, я не обратил на это внимания. Исправлено. Теперь он также будет считать те с пустым текстом или когда он содержит только пробелы. Я добавил RTRIM на всякий случай, но во время тестирования я обнаружил, что LEN varchar с только пробелами также равен 0. Интересная небольшая сложность T-SQL. – LukStorms

Смежные вопросы