计算具有未知列名的非空行

时间:2016-03-21 14:53:56

标签: sql-server tsql pivot

如果表中有未知列名,如何列出所有列名和非空(NULL空字符串<的行数/ em>)该列中的值?

小例子:

Col1 | Col2 | Col3 | dkasldk | dD? d3# !(
1    |      | 2    |         | 
     | 2    | d    | ddd939  |
f    | f    | 84   |         |

应该屈服:

Column Name | Values
Col1        | 2
Col2        | 2
Col3        | 3
dkasldk     | 1
dD? d3# !(  | 0

我已经尝试过使用INFORMATION_SCHEMA.COLUMNS并创建动态SQL查询,但无济于事:

select N'select c.COLUMN_NAME,
(select sum(case when p.' + QUOTENAME(c.COLUMN_NAME) + ' != '''' then 1 else 0 end) from [Produkte] p) [Produkte]
from INFORMATION_SCHEMA.COLUMNS c
where c.TABLE_NAME = ''Produkte'' and c.COLUMN_NAME = ''' + c.COLUMN_NAME + '''' select_statement
from INFORMATION_SCHEMA.COLUMNS c
where c.TABLE_NAME = 'Produkte'

我无法完全理解如何结合动态列名计算空值的两个问题(我确实找到了自己的解决方案,但不是组合) ...

3 个答案:

答案 0 :(得分:1)

你可以使用UNPIVOT做这样的事情。

DECLARE @TableName NVARCHAR(MAX) = N'Produkte',
        @CountColumns NVARCHAR(MAX),
        @Columns NVARCHAR(MAX),
        @Sql NVARCHAR(MAX)

SELECT  @CountColumns = COALESCE(@CountColumns + ',', '') + 'COUNT(NULLIF(' + QUOTENAME(c.COLUMN_NAME) + ','''')) AS ' + QUOTENAME(c.COLUMN_NAME),
        @Columns = COALESCE(@Columns + ',', '') + QUOTENAME(c.COLUMN_NAME)
FROM    INFORMATION_SCHEMA.COLUMNS c
WHERE   c.TABLE_NAME = @TableName

SET     @SQL = 'SELECT [Column Name], [Values] 
                FROM (
                    SELECT '
                        + @CountColumns + '
                    FROM    ' + @TableName + '
                ) t
                UNPIVOT (
                    [Values]
                    FOR [Column Name] IN (' + @Columns + ')
                ) up
'
EXEC(@SQL)

SQL Fiddle Demo

答案 1 :(得分:1)

您可以使用动态UNPIVOT

使用这些变量:

DECLARE @qry NVARCHAR(MAX) 
DECLARE @cols NVARCHAR(MAX) = ''

您可以使用以下动态sql以适合UNPIVOT操作的格式选择列名称:

SELECT @cols = STUFF((SELECT ',[' + c.COLUMN_NAME + ']'
                      FROM INFORMATION_SCHEMA.COLUMNS c
                      WHERE c.TABLE_NAME = 'Produkte'
                      FOR XML PATH('')), 1, 1, '') 

最后使用@cols构建查询:

SET @qry = 'SELECT t.Col, COUNT(*) 
            FROM (SELECT Val, Col
                  FROM Produkte
                  UNPIVOT ( 
                     Val FOR Col IN (' + @cols + ')) unpvt
            ) AS t
            WHERE t.Val <> '''' OR t.Val IS NOT NULL
            GROUP BY t.Col'

...并执行它以获得所需的结果:

EXEC(@qry)

答案 2 :(得分:1)

最终你所追求的SQL是这样的:

SELECT  ColumnName, NonEmpty 
FROM (  SELECT  A = 1, 
                [Col1] = COUNT(CASE WHEN [Col1] <> '' THEN 1 END),
                [Col2] = COUNT(CASE WHEN [Col2] <> '' THEN 1 END),
                [Col3] = COUNT(CASE WHEN [Col3] <> '' THEN 1 END),
                [dkasldk] = COUNT(CASE WHEN [dkasldk] <> '' THEN 1 END),
                [dD? d3# !(] = COUNT(CASE WHEN [dD? d3# !(] <> '' THEN 1 END) 
        FROM #T
    ) AS t 
    UNPIVOT 
    (   NonEmpty 
        FOR ColumnName IN ([Col1],[Col2],[Col3],[dkasldk],[dD? d3# !(])
    ) AS upvt;

UNPIVOT将从

转换您的数据
Col1    Col2    Col3
-------------------------
1       3       2

达到您需要的格式:

ColumnName  NonEmpty
-------------------------
Col1        1
Col2        3
Col3        2

您可以使用以下内容动态构建:

-- SAMPLE DATA
USE TempDB;
CREATE TABLE #T 
(   
    [Col1] VARCHAR(1), 
    [Col2] VARCHAR(1), 
    [Col3] VARCHAR(2), 
    [dkasldk] VARCHAR(6), 
    [dD? d3# !(] VARCHAR(1)
);

INSERT #T ([Col1], [Col2], [Col3], [dkasldk], [dD? d3# !(])
VALUES
    ('1', NULL, '2', NULL, ''),
    ('', '2', 'd', 'ddd939', NULL),
    ('f', 'f', '84', NULL, '');


DECLARE @TableName SYSNAME = '#T';

-- VALID INPUT TABLE
IF OBJECT_ID(@TableName, 'U') IS NULL 
    AND OBJECT_ID(@TableName, 'V') IS NULL
BEGIN
    PRINT 'Invalid table or View';
    RETURN
END 

-- BUILD DYNAMIC SQL
DECLARE @SQL NVARCHAR(MAX) = 
    CONCAT('SELECT  ColumnName, NonEmpty FROM (SELECT A = 1, ' ,
            STUFF(( SELECT  CONCAT(',', 
                                    QUOTENAME(name), 
                                    ' = COUNT(CASE WHEN ', 
                                    QUOTENAME(Name), 
                                    ' <> '''' THEN 1 END)')
                    FROM    sys.columns
                    WHERE   [object_id] = OBJECT_ID(@TableName)
                    FOR XML PATH(''), TYPE
                ).value('.', 'NVARCHAR(MAX)'), 1, 1, ''),
        ' FROM ',
        @TableName,
        ') AS t UNPIVOT (NonEmpty FOR ColumnName IN (',
            STUFF(( SELECT  CONCAT(',', QUOTENAME(name))
                    FROM    sys.columns
                    WHERE   [object_id] = OBJECT_ID(@TableName)
                    FOR XML PATH(''), TYPE
                ).value('.', 'NVARCHAR(MAX)'), 1, 1, ''),
        ')) AS upvt');

-- EXECUTE DYNAMIC SQL
EXECUTE sp_executesql @SQL;