部分计数汇总

时间:2020-01-16 11:05:12

标签: sql sql-server tsql query-performance

注意:尽管我目前的重点是tsql,但这很可能是一个更一般的sql问题。

请考虑以下有效但也可伪代码的示例查询:

select 
    desiredKeyCols,
    case count(distinct productID) 
        when 0 then '0'
        when 1 then '1'
        else '2+'
    end as [Product Count Classification]
from orders
group by desiredKeyCols

对于每个desiredKeyCols,如果没有关联的productID,则[产品计数分类]字段将返回0;对于1,返回1;对于更高的数字,返回2+。但是,count(distinct productID)一旦达到2就不会停止其计算。它会很高兴地继续到无穷大,然后另一个操作将计算大小写。

我看到同一件事多次出现。

是否有更有效的方法来实现此目的?如果我们只希望0/1 +类,答案是半联接(存在)。但是任意数量的范围呢?

1 个答案:

答案 0 :(得分:1)

您可能无能为力。但是,这里有两种替代的方式来表达可能具有更好性能的查询。

如果您在“(desiredKeycols,productid)”上有一个索引,并且可能在“(desiredKeycols,productid desc)”上有一个索引,则可以尝试:

select desiredKeycols,
       (case distinct_cnt . . . )
from (select o.*,
             (dense_rank() over (partition by desiredKeycols order by productid) +
              dense_rank() over (partition by desiredKeycols order by productid desc)
             ) as distinct_cnt
      from orders o
     ) o
group by desiredKeycols;

这不会在“ 3”处停止,但有可能比count(distinct)的优化效果更好。

实际上,稍作选择只能使用一个索引:

select desiredKeycols,
       (case cnt . . . )
from (select o.desiredKeycols, count(*) as cnt
      from orders o
      group by desiredKeycols, productid
     ) o
group by desiredKeycols;

在某些数据库中,这比count(distinct)快得多。但是,我认为SQL Server具有更好的优化器,因此这可能不是一个大胜利。