想要查看空值较小的数据

时间:2014-11-02 19:46:41

标签: sql sql-server database sql-server-2012

我加入了一个非常复杂的新项目。我们使用的是SQL Server 2012,并且拥有许多数据库(15+)。每个数据库中的每个表都有许多列(超过25 - 50) 每张表中有数千条记录。我想以最好的方式查看数据。但是,某些列有空值。我很难对每个表中存在的数据有所了解。

以下是我对样本数据的质疑。

Id |Column1 |Column2   | Column3 |Column4 |............|ColumnNth
1  |  sam   |*NULL*    |   2     | *NULL* |............|mike  
2  |  jack  |2014-02-03| *NULL*  |   6    |............|*NULL*  
3  |  Rav   | *NULL*   | *NULL*  |  *NULL*|............|Jim  
4  | *NULL* |2013-09-08|   7     |  922   |............|Rocky  
5  |  Tom   |2014-10-08|   11    |  212   |............|Mary  

...
...
等......

例如,下面是每行所有列的NULL计数。 [它不是数据库中的表。 " NULL计数"不是初始表的列。我只是为了便于解释而展示了这一点]

ID| Count of NULLs  
1 | 5  
2 |2  
3 |10  
4 |1  
5 |0  
6 | 1  
7 | 2  
8 | 3  

...
...
等等。
现在我想在顶部查看数量较少的NULL数据。数据的顺序应按以下顺序排列。我只显示了ID的顺序,以便不再输入所有数据(列)。

ID 
5  
4  
6  
2  
7  
8  
1  

...
...
3
...
等......

输出说明:
1.行(ID = 5)的所有列的空值总数为零。这应该是第一个 2.行(ID = 4)和行(ID = 6)的所有列的空值总数为1。 ID = 4且ID = 6的行后面应该是ID = 5。 ......等等......

在输出中,我不希望 NULL 被其他值替换为0或1或空值等。因此 NULL 应显示为如果它存在于初始表中,则它在输出中 我想查看所有列

请给我一个通用的存储过程或查询或一组查询。由于列数超过25-40,SP或查询应该可以在不指定列名的情况下工作。如果是存储过程,那么表名将是它的输入 我认为为此要求编写SP非常复杂。但我所问的是一个新的开发人员在他/她加入支持/维护项目时面临的实时情况,这个项目已经构建并包含大量数据的复杂庞大的数据库。感谢

2 个答案:

答案 0 :(得分:1)

下面是一个示例,您可以根据实际表格的需要进行扩展。

SELECT 
      Id
    , (SELECT COUNT(*) 
       FROM (VALUES(Column1), (Column2), (Column3), (Column4)) AS AllColumns(ColumnValue) 
       WHERE AllColumns.ColumnValue IS NULL) AS NullCount
FROM dbo.SampleTable
ORDER BY NullCount;

如果源表架构可能不同,则您需要使用动态SQL:

DECLARE @ColumnList nvarchar(MAX) = 
    (SELECT
    STUFF((SELECT ',(' + name + ')'
    FROM sys.columns
    WHERE
        object_id = OBJECT_ID(N'dbo.SampleTable')
        AND name <> 'Id'
    FOR XML PATH('')),1 ,1, '')
    );

DECLARE @SQL nvarchar(MAX) = N'
    SELECT 
          Id
        , (SELECT COUNT(*) 
           FROM (VALUES' + @ColumnList + ') AS AllColumns(ColumnValue) 
           WHERE AllColumns.ColumnValue IS NULL) AS NullCount
    FROM dbo.SampleTable
    ORDER BY NullCount;';

EXEC sp_executesql @SQL;

编辑(添加说明和SQL 2005方法):

通过查询指定表中所有列的sys.columns目录视图来生成列列表,Id除外(您可以根据需要使用相同的技术省略其他列)。每个包含的列都括在括号中,并用逗号分隔,以构建VALUES子句所需的字符串。 FOR XML子句将此列表返回一个字符串,并使用STUFF函数删除无关的前导逗号,以便@ColumnList变量包含VALUES子句所需的字符串。最后的SQL语句是通过连接SELECT语句的其余部分构建的。

表值行构造函数(http://msdn.microsoft.com/en-us/library/dd776382.aspx)允许通过VALUES子句指定一行或多行。这在最终查询中用于将每个源行的列列表转换为行,以便使用COUNT聚合函数。

此处使用的技术(DECLARE语句中的行构造函数和初始化变量)是在SQL Server 2008中引入的,因此在早期的SQL Server版本中不起作用。下面的版本使用派生表而不是表值行构造函数,它将与SQL 2005一起使用。

DECLARE @ColumnList nvarchar(MAX) = 
    (SELECT
    STUFF((SELECT ' UNION ALL SELECT ' + name
    FROM sys.columns
    WHERE
        object_id = OBJECT_ID(N'dbo.SampleTable')
        AND name <> 'Id'
    FOR XML PATH('')),1 ,11, '')
    );

DECLARE @SQL nvarchar(MAX) = N'
    SELECT 
          Id
        , (SELECT COUNT(*) 
           FROM (' + @ColumnList + ') AS AllColumns(ColumnValue) 
           WHERE AllColumns.ColumnValue IS NULL) AS NullCount
    FROM dbo.SampleTable
    ORDER BY NullCount;';

EXEC sp_executesql @SQL;

答案 1 :(得分:0)

没有纯SQL查询会计算表中的NULL列,而没有说明列的名称。

如果您可以使用过程,则可以获取列名并通过从INFORMATION_SCHEMA.COLUMNS获取列名并将它们连接起来来动态构建查询,如下面的查询(或其他替代声明here):< / p>

SELECT A.*,
  ( (CASE WHEN Column1 IS NULL THEN 1 ELSE 0 END)
  + (CASE WHEN Column2 IS NULL THEN 1 ELSE 0 END)
  + (CASE WHEN Column3 IS NULL THEN 1 ELSE 0 END)
  .
  .
  .
  + (CASE WHEN ColumnN IS NULL THEN 1 ELSE 0 END)) AS NULL_CNT
FROM MYTABLE A
ORDER BY NULL_CNT DESC