2016-09-05 11 views
6

Mam tabelę z nieznaną liczbą kolumn (i nieznanych nazw kolumn) z różnymi typami danych (może być wszystko, od bitu do nvarchar lub datetime), jak poniżej:Liczba pustych komórek SQL w nieznanej liczbie kolumn

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

muszę zapytać który zlicza wszystkie NULL i pustych komórek w każdej kolumnie i wysyła wynik takiego:

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

rozumiem, że muszę używać dynamicznych zapytań i UNPIVOT, ale moja znajomość SQL nie ma tego w pobliżu!

How to count all NULL values in a table? nie wydają się działać jak to jest MySQL związanych, nie MS SQL

+0

Możliwy duplikat [Jak policzyć wszystkie wartości NULL w tabeli?] (Http://stackoverflow.com/questions/2295318/how-to-count-all -null-values-in-a-table) – webmaster

+1

@webmaster, twój * możliwy duplikat * jest dla 'MySQL' podczas gdy to działa przeciwko' SQL Server' – Shnugo

+0

Tak rozumiany późno, dziękuję bardzo. – webmaster

Odpowiedz

3

można spróbować tego dynamicznego kodu SQL out:

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

Musiałem edytować drugie dynamiczne zapytanie, aby uwzględnić wartości Null (ponieważ potrzebowałem wyników w jednym formacie tabelarycznym), ale zadziałało jak wdzięk, dzięki! – espressionist

0

EDIT: Ta odpowiedź jest dla MySQL (nie czytać ostrożnie na początku)

Od this answer, myślę, że to wynik będzie liczyć wszystkie "null" komórki:

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

Dziękuję za szybką odpowiedź, ale twoja odpowiedź odnosi się do MySQL i nie działa w MSSQL – espressionist

+0

Ach tak przepraszam, po prostu błędnie oszacowałem. Dzięki za ostrzeżenie. – webmaster

1

Oto metoda zwracania pól z pustymi lub zerowymi wartościami z tabeli.
Poprzez generowanie i wykonywanie zapytania dynamicznego z niepustą.
Testowane na 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

Po prostu przetestowałem to sam, działa ładnie z NULL, ale muszę również uwzględnić puste komórki! – espressionist

+0

@Spresjonista Rzeczywiście, przeoczyłem to. Naprawiono teraz. Teraz policzy również te z pustym tekstem lub gdy zawiera tylko spacje. Na wszelki wypadek dodałem RTRIM, ale podczas testów odkryłem, że LEN w varchar z tylko spacjami równe jest 0. Ciekawe małe T-SQL. – LukStorms