Найдите% отсутствующих в каждом столбце таблицы T- SQL - PullRequest
0 голосов
/ 06 августа 2020

Я пытаюсь понять, как написать запрос, чтобы найти% отсутствия (значения NULL) в каждом столбце таблицы на SQL сервере, поэтому идея состоит в том, чтобы запрос возвращал два столбца:

  1. первый столбец - это имена каждого столбца в таблице
  2. второй столбец должен быть%, отсутствующим в этом столбце.

Я продолжаю пытаться примените оператор case к каждому столбцу, но он не работает, любая помощь приветствуется!

1 Ответ

0 голосов
/ 06 августа 2020

Хорошо, беря первый ответ Я связал, вы можете сделать следующий запрос:

USE Sandbox;
GO

DECLARE @Schema sysname, @Table sysname, @IncDistinct bit = 0;
SET @Schema = 'dbo';
SET @Table = 'rCTEvsTally';

DECLARE @SQL nvarchar(MAX)

SET @SQL = N'WITH Counts AS (' + NCHAR(13) + NCHAR(10) + 
           N'    SELECT @Schema AS SchemaName,' + NCHAR(13) + NCHAR(10) +
           N'           @Table AS TableName,' +
           STUFF((SELECT N',' + NCHAR(13) + NCHAR(10) + 
                           N'           COUNT(' + CASE WHEN C.DATA_TYPE IN ('text','image') THEN 'NULL' ELSE N'CASE WHEN ' + QUOTENAME(C.COLUMN_NAME) + N' IS NULL THEN 1 END' END + N') AS ' + QUOTENAME(COLUMN_NAME + N'_NULLs') + N',' + NCHAR(13) + NCHAR(10) +
                           N'           COUNT(' + CASE WHEN C.DATA_TYPE IN ('text','image') THEN '1' ELSE QUOTENAME(C.COLUMN_NAME) END + N') AS ' + QUOTENAME(COLUMN_NAME) + N',' + NCHAR(13) + NCHAR(10) +
                           N'           COUNT(DISTINCT ' + CASE WHEN C.DATA_TYPE IN ('text','image') THEN '1' ELSE QUOTENAME(C.COLUMN_NAME) END + N') AS ' + QUOTENAME(COLUMN_NAME + N'_Distinct')
                   FROM INFORMATION_SCHEMA.COLUMNS C
                   WHERE C.TABLE_SCHEMA = @Schema
                       AND C.TABLE_NAME = @Table
                       --AND C.DATA_TYPE NOT IN ('text','image')
                   ORDER BY C.ORDINAL_POSITION
                   FOR XML PATH(N''),TYPE).value('.','nvarchar(MAX)'),1,14,N'') + NCHAR(13) + NCHAR(10) + 
           N'    FROM ' + QUOTENAME(@Schema) + N'.' + QUOTENAME(@Table) + N')' + NCHAR(13) + NCHAR(10) + 
           N'SELECT V.OrdinalPosition,' + NCHAR(13) + NCHAR(10) + 
           N'       V.ColumnName,' + NCHAR(13) + NCHAR(10) + 
           N'       V.NonNullCount,' + NCHAR(13) + NCHAR(10) + 
           CASE WHEN @IncDistinct = 1 THEN N'       V.DistinctCount,' + NCHAR(13) + NCHAR(10) ELSE N'' END +
           N'       V.NullCount,' + NCHAR(13) + NCHAR(10) + 
           N'       ISC.DATA_TYPE + ISNULL(NULLIF(DT.S,''(*)''),'''') AS Datatype,' + NCHAR(13) + NCHAR(10) +
           N'       K.KeyType' + NCHAR(13) + NCHAR(10) +
           N'FROM Counts C' + NCHAR(13) + NCHAR(10) + 
           N'     CROSS APPLY(VALUES' + STUFF((SELECT N',' + NCHAR(13) + NCHAR(10) + 
                                                       N'                       (' + CONVERT(varchar(4),C.ORDINAL_POSITION) +N',N' + QUOTENAME(C.COLUMN_NAME,'''') + N',C.' + QUOTENAME(C.COLUMN_NAME) + N',C.' + QUOTENAME(C.COLUMN_NAME + N'_Distinct') + N',C.' + QUOTENAME(C.COLUMN_NAME + N'_NULLs') + N')'
                                               FROM INFORMATION_SCHEMA.COLUMNS C
                                               WHERE C.TABLE_NAME = @Table
                                                 --AND C.DATA_TYPE NOT IN ('text','image')
                                               ORDER BY C.ORDINAL_POSITION
                                               FOR XML PATH(N''),TYPE).value('.','nvarchar(MAX)'),1,26,N'') + N')V(OrdinalPosition,ColumnName,NonNullCount,DistinctCount,NullCount)' + NCHAR(13) + NCHAR(10) +
           N'     JOIN INFORMATION_SCHEMA.COLUMNS ISC ON C.SchemaName = ISC.TABLE_SCHEMA' + NCHAR(13) + NCHAR(10) +
           N'                                        AND C.TableName = ISC.TABLE_NAME' + NCHAR(13) + NCHAR(10) +
           N'                                        AND V.ColumnName = ISC.COLUMN_NAME' + NCHAR(13) + NCHAR(10) + 
           N'     CROSS APPLY (VALUES(''('' + STUFF(CONCAT('','' + CASE ISC.CHARACTER_MAXIMUM_LENGTH WHEN -1 THEN ''MAX'' ELSE CONVERT(varchar(4),ISC.CHARACTER_MAXIMUM_LENGTH) END,' + NCHAR(13) + NCHAR(10)+
           N'                                            '','' + CASE WHEN ISC.DATA_TYPE NOT LIKE ''%int'' THEN CONVERT(varchar(4),ISC.NUMERIC_PRECISION) END,' + NCHAR(13) + NCHAR(10) +
           N'                                            '','' + CASE WHEN ISC.DATA_TYPE NOT LIKE ''%int'' THEN CONVERT(varchar(4),ISC.NUMERIC_SCALE) END,' + NCHAR(13) + NCHAR(10) +
           N'                                            '','' + CASE WHEN ISC.DATA_TYPE NOT IN (''datetime'',''smalldatetime'') THEN CONVERT(varchar(4),ISC.DATETIME_PRECISION) END),1,1,'''') + '')'')) DT(S)' + NCHAR(13) + NCHAR(10) +
           N'     OUTER APPLY(SELECT TC.CONSTRAINT_TYPE AS KeyType ' + NCHAR(13) + NCHAR(10) + 
           N'                 FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS TC' + NCHAR(13) + NCHAR(10) + 
           N'                      JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE KCU ON TC.TABLE_SCHEMA = KCU.TABLE_SCHEMA' + NCHAR(13) + NCHAR(10) + 
           N'                                                                  AND TC.TABLE_NAME = KCU.TABLE_NAME' + NCHAR(13) + NCHAR(10) + 
           N'                                                                  AND TC.CONSTRAINT_NAME = KCU.CONSTRAINT_NAME' + NCHAR(13) + NCHAR(10) + 
           N'                 WHERE KCU.COLUMN_NAME = V.ColumnName' + NCHAR(13) + NCHAR(10) + 
           N'                   AND TC.TABLE_SCHEMA = ISC.TABLE_SCHEMA' + NCHAR(13) + NCHAR(10) + 
           N'                   AND TC.TABLE_NAME = ISC.TABLE_NAME) K' + NCHAR(13) + NCHAR(10) +
           N'ORDER BY V.OrdinalPosition';

PRINT @SQL; --you will need to use the SELECT here if @SQL is over 4,000 characters
--SELECT @SQL;
EXEC sp_executesql @SQL, N'@Schema sysname,@Table sysname',@Schema = @Schema, @Table = @Table;

Это показывает различные значения для параметризованной таблицы.

Вместо того, чтобы вырезать это решение, вы можете затем INSERT этот набор данных во (временную) таблицу, а затем выполнить работу.

--All prior code goes above apart from the call to sp_executesql
CREATE TABLE #ColumnCounts (OrdinalPosition int,
                            ColumnName sysname,
                            NonNullCount decimal(15,0), --Decimal as we want a percentage later
                            NullCount decimal(15,0), --Decimal as we want a percentage later
                            Datatype sysname,
                            KeyType nvarchar(50));
INSERT INTO #ColumnCounts
EXEC sys.sp_executesql @SQL, N'@Schema sysname,@Table sysname',@Schema = @Schema, @Table = @Table;

SELECT CC.ColumnName,
       NullCount / (NonNullCount + NullCount) AS ["Missingness"]
FROM #ColumnCounts CC;

DROP TABLE #ColumnCounts;

Как я утверждаю на многих моих сложных Dynami c SQL решений, это не начальный уровень. Если вы этого не понимаете, вам, вероятно, не следует его использовать, или вам нужно найти время, чтобы понять это. Если вы хотите начать понимать это, я предлагаю сначала взглянуть на сгенерированный SQL, а затем работать в обратном направлении.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...