【问题标题】:SQL Sever Getting Distinct Count using "Group By ... With Cube"SQL Server 使用“Group By ... With Cube”获取不同的计数
【发布时间】:2011-05-04 16:10:53
【问题描述】:

基本上,我试图在这个立方结果中获得不同的计数。但不幸的是,您不能将 Count(distinct(Field)) 与多维数据集和汇总一起使用 (as stated here)

这是数据的样子。 (这只是一个简单的例子,我确实希望数据中有重复)

    Category1       Category2       ItemId
    a               b               1
    a               b               1
    a               a               1
    a               a               2
    a               c               1
    a               b               2
    a               b               3
    a               c               2
    a               a               1
    a               a               3
    a               c               4

这是我想做的,但它不起作用。

SELECT
  Category1,
  Category2,
  Count(Distinct(ItemId))
FROM ItemList IL
GROUP BY
  Category1,
  Category2
WITH CUBE

我知道我可以像这样进行子选择来获得我想要的结果:

SELECT
  *,
  (SELECT
     Count(Distinct(ItemId)) 
   FROM ItemList IL2 
   WHERE 
     (Q1.Category1 IS NULL OR Q1.Category1 IS NOT NULL AND Q1.Category1 = IL2.Category1) 
     AND
     (Q1.Category2 IS NULL OR Q1.Category2 IS NOT NULL AND Q1.Category2 = IL2.Category2))
       AS DistinctCountOfItems 
FROM (SELECT
        Category1,
        Category2
      FROM ItemList IL
      GROUP BY
        Category1,
        Category2
      WITH CUBE) Q1

但是当由于子选择导致结果集很大时,这会运行缓慢。有没有其他方法可以从立方结果中获得不同的计数?

这是我想看到的结果

Category1     Category2    DistinctCountOfItems
a             a            3
a             b            3
a             c            3
a             NULL         4
NULL          NULL         4
NULL          a            3
NULL          b            3
NULL          c            3

【问题讨论】:

    标签: sql sql-server tsql sql-server-2000 group-by


    【解决方案1】:

    这很有趣。我可以在 SQL Server 2008 R2 中运行您的第一个查询,但文档说它不起作用。

    这是您的第二个查询的变体,它可能会执行得更好。它在子查询中执行不同计数,在外部查询中执行多维数据集

    SELECT Category1, Category2, MAX(DistinctCount) as DistinctCount
    FROM (
        SELECT Category1, Category2, COUNT(DISTINCT ItemId) as DistinctCount
        FROM ItemList
        GROUP BY Category1, Category2
        ) Q1
    GROUP BY Category1, Category2
    WITH CUBE
    

    【讨论】:

    • .. 实际上,当数据在表中重复时,这不起作用。查看问题中的修订数据。它没有返回预期的结果。
    【解决方案2】:

    这个怎么样??

    内部查询将返回不同的结果。

    SELECT ORIGINAL_ITEM.Category1, DISTINCT_ITEM.Category2, DISTINCT_ITEM.cnt
    FROM
      ( SELECT DISTINCT category2, COUNT(*) as CNT
        FROM ItemList ) DISTINCT_ITEM
    JOIN ItemList ORIGINAL_ITEM on ORIGINAL_ITEM.category2 = DISTINCT_ITEM.category2 
    GROUP BY ORIGINAL_ITEM.category1, DISTINCT_ITEM.category2 
    

    【讨论】:

    • 这甚至无效...您不能在 group by 的选择列表中包含不包含在聚合或 group by 子句中的项目。
    • 同意。没有实际测试查询。所以如果我添加“分组依据”内部查询,这会是有效的想法吗?
    【解决方案3】:

    我有以下版本:

    Microsoft SQL Server 2008 R2 (RTM) - 10.50.1600.1 (Intel X86) Apr 2 2010 15:53:02 版权所有 (c) Microsoft Corporation Express Edition with Advanced Services on Windows NT 5.1 (Build 2600: Service Pack 3)

    当我运行您的查询时

    SELECT 
      Category1, 
      Category2, 
      COUNT(DISTINCT(ItemId))
    FROM ItemList IL 
    GROUP BY 
      Category1, 
      Category2 
    WITH CUBE 
    

    我得到这些结果

    a       a       3
    a       b       3
    a       c       3
    NULL    a       3
    NULL    b       3
    NULL    c       3
    a       NULL    4
    NULL    NULL    4
    

    【讨论】:

    • Code Gunny 我知道这适用于 SQL Server 2008。但我的问题是关于 SQL Server 2000。你的帖子无关紧要
    • @John - 我想我需要更加注意标签,呵呵。
    【解决方案4】:

    这是我发现的另一种可能性,但它非常混乱。但是它比使用子选择运行得更快。

    SELECT 
      category1, 
      category2, 
      count(distinct itemid)
    FROM (SELECT DISTINCT 
            category1, 
            category2, 
            itemid
          FROM ItemList
    ) x
    GROUP BY category1, category2
    UNION ALL
    SELECT 
      category1, 
      NULL, 
      count(distinct itemid)
    FROM (SELECT DISTINCT 
            category1, 
            category2, 
            itemid
          FROM ItemList
    ) x
    GROUP BY category1
    UNION ALL
    SELECT 
      NULL, 
      category2, 
      count(distinct itemid)
    FROM (SELECT DISTINCT 
            category1, 
            category2, 
            itemid
          FROM ItemList
    ) x
    GROUP BY category2
    UNION ALL
    SELECT 
      NULL, 
      NULL, 
      count(distinct itemid)
    FROM (SELECT DISTINCT 
            category1, 
            category2, 
            itemid
          FROM ItemList
    ) x
    

    【讨论】:

      【解决方案5】:

      你应该能够像这样清理你的“凌乱”的答案:

      select Category1, Category2, count(distinct ItemId)
      from ItemList
      group by Category1, Category2
      UNION ALL
      select Category1, null, count(distinct ItemId)
      from ItemList
      group by Category1
      UNION ALL
      select null, Category2, count(distinct ItemId)
      from ItemList
      group by Category2
      UNION ALL
      select null, null, count(distinct ItemId)
      from ItemList
      

      然后我想出了另一个选择:

      select IL1.Category1, IL1.Category2, count(distinct ItemId)
      from ( 
        select Category1, Category2
        from ItemList
        group by Category1, Category2
        with cube
       ) IL1
       join ItemList IL2 on (IL1.Category1=IL2.Category1 and IL1.Category2=IL2.Category2)
            or (IL1.Category1 is null and IL1.Category2=IL2.Category2)
            or (IL1.Category2 is null and IL1.Category1=IL2.Category1)
            or (IL1.Category1 is null and IL1.Category2 is null)
      group by IL1.Category1, IL1.Category2
      

      效率可能因索引、被分组的列数等而异。对于我编写的测试表,子选择和连接(相对于联合)稍好一些。我目前无权访问 MSSQL 2000 实例(我在 2005 实例上进行了测试),但我认为这里没有任何内容是无效的。

      更新

      一个更好的选择,特别是如果您对超过 2 列进行分组(如果您按 8 列进行分组,上述代码将需要 256 个连接子句来捕获所有空组合!):

      select IL1.Category1, IL1.Category2, count(distinct ItemId)
      from ( 
        select Category1, Category2
        from ItemList
        group by Category1, Category2
        with cube
       ) IL1
       inner join ItemList IL2 on isnull(IL1.Category1,IL2.Category1)=IL2.Category1
                        and isnull(IL1.Category2,IL2.Category2)=IL2.Category2
      group by IL1.Category1, IL1.Category2
      

      【讨论】:

      • @chezy525....不错的方法...我喜欢。它肯定比工会更有效率。仍然比我喜欢的要混乱一些,但它有效。
      • 谢谢!这是我星期五的一个有趣的消遣!我认为如果没有明显的聚合支持,任何解决方案都会“比应有的更混乱”......
      • 你的最后一个选项与我最终得到的相同,它是最优雅的一个,并且它击中桌子的次数最少,以便得到结果。据我从执行计划中可以看出,Category1、Category2、ItemID 上的索引将使查询尽可能快。
      • 我多么想念 Postgresql.. 你只需要 SELECT COUNT(*), ColumnToGroupBy FROM Table GROUP BY ColumnToGroupBy
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-20
      • 1970-01-01
      • 2017-03-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多