【问题标题】:SQL Server count number of distinct values in each column of a tableSQL Server 计算表每列中不同值的数量
【发布时间】:2018-03-22 02:57:40
【问题描述】:

我有一个大约 150 列的表格。我想为每一列找到count(distinct(colName)),但我想知道是否有办法在不实际输入每一列名称的情况下这样做。

理想情况下我会使用count(distinct(*)),但这不起作用。

还有其他建议吗?

编辑:

如果这是我的桌子:

  id         col1         col2        col3      ...
  01         10001       west         north  
  02         10001       west         south  
  03         10002       east         south  
  04         10002       west         north  
  05         10001       east         south  
  06         10003       west         north 

我正在寻找这个输出

count(distinct(id))   count(distinct(col1))    count(distinct(col2))   count(distinct(col3))
       6                       3                    2                      2

【问题讨论】:

  • 等一下,一个表是否可以多次使用一个列名?或者你有一个存储列名值的字段?

标签: sql sql-server


【解决方案1】:

你可以这样做:

DECLARE @query varchar(max)
    SELECT @query = 
    'SELECT ' + SUBSTRING((SELECT ',' +'COUNT(DISTINCT(' + column_name + ')) 
             As ' + column_name + ' '  
             FROM information_schema.columns
             WHERE 
             table_name = 'table_name'
             for xml path('')),2,200000)  +  'FROM table_name'

PRINT(@query)

【讨论】:

    【解决方案2】:

    使用以下脚本构建 T-SQL 查询,该查询将返回表中每一列的不同计数。将 @Table 值替换为您的表名。

    DECLARE @Table SYSNAME = 'TableName'; 
    
    -- REVERSE and STUFF used to remove trailing UNION in string
    SELECT REVERSE(STUFF(REVERSE((SELECT 'SELECT ''' + name 
                                         + ''' AS [Column], COUNT(DISTINCT(' 
                                         + QUOTENAME(name) + ')) AS [Count] FROM ' 
                                         + QUOTENAME(@Table) + ' UNION ' 
                                  -- get column name from sys.columns  
                                  FROM   sys.columns 
                                  WHERE  object_id = Object_id(@Table)
                                  -- concatenate result strings with FOR XML PATH
                                  FOR XML PATH (''))), 1, 7, ';'));
    

    【讨论】:

    • 很好的答案!这会按字母顺序对列进行排序,当有很多 (150) 列时,这效果不太好。我将添加一个基于此的答案而不是编辑此答案(对于窄表,这很好用!)。
    【解决方案3】:

    来自 Bryan 的扩展答案。他的出色答案按字母顺序列出了这些字段。
    如果您有十几个字段,这没问题。如果您有 150 个字段,如 OP 所述,这会使这些字段保持其表的顺序。
    我修改了他的查询以检查 213 列(供应商的)表,并希望发布以供将来参考。

    DECLARE @Table SYSNAME = 'Your table name; without schema; no square brackets'; 
    
    -- REVERSE and STUFF used to remove trailing UNION in string
    SELECT REVERSE(STUFF(REVERSE((SELECT 'SELECT ' 
            + CAST(column_id AS VarChar(4)) + ' AS [column_id],' -- extra column
            + '''' + name 
            + ''' AS [Column], COUNT(DISTINCT(' 
            + QUOTENAME(name) + ')) AS [Count] FROM ' 
            + QUOTENAME(@Table) + ' UNION ' 
        -- get column name from sys.columns  
        FROM   sys.columns 
        WHERE  system_type_id NOT IN (34,240) AND object_id = Object_id(@Table) 
        ORDER BY column_id -- keeps columns in table order
        -- concatenate result strings with FOR XML PATH
        FOR XML PATH (''))), 1, 7, ';'));
    

    我决定不编辑 Bryan 的答案,因为人们通常不需要额外的列。
    (如果您不添加 column_id 列,则 ORDER BY 无效。我相信这是因为只有最外面的 ORDER BY 才能保证对最终输出进行排序;我希望有一个 msft 参考来证实这一点)

    编辑:对字段类型 Image 和 Geography 使用函数 Count 会引发错误。
    添加了“system_type_id NOT IN (34,240)”。

    【讨论】:

    • 我想使用 sp_executesql 将其全部打包到一个查询中,但没有时间。如果有人发布答案,我会投票赞成:-)
    【解决方案4】:

    我不相信仅使用 MySQL 是可能的。 我认为您将不得不使用服务器端语言来获得您想要的结果。

    使用“DESC TABLE”作为您的第一个查询,然后为每个“字段”行编译您的查询。


    忽略这个,错误的系统标签:)

    【讨论】:

      【解决方案5】:

      应该这样做:

      select count(*) from (select distinct * from myTable) as t
      

      这里是SQL Fiddle 测试。

      create table Data
      (
          Id int,
          Data varchar(50)
      )
      
      insert into Data 
      select 1, 'ABC'
      union all
      select 1, 'ABC'
      
      select count(*) 
      from (select distinct * from Data) as t
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-01-09
        • 2021-02-26
        • 1970-01-01
        • 1970-01-01
        • 2019-10-11
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多