单个 SQL 查询的多个 COUNTS:寻找效率

Several COUNTS on single SQL Query: Looking for efficiency

我只想了解您对查询效率的看法。我正在通过非常大的 table (几百万条记录)计算值。这是 MSSQL,但我认为它应该适用于任何数据库引擎。我现在正在做的是:

SELECT Task,
    COUNT(*) as Total,
    SUM(CASE WHEN Status = 'Active' THEN 1 ELSE 0 END) AS Active,
    SUM(CASE WHEN Status = 'Active' AND AppType = 'MOBILE' THEN 1 ELSE 0 END) AS ActiveMobile,
    SUM(CASE WHEN Status = 'Active' AND AppType = 'WEB' THEN 1 ELSE 0 END) AS ActiveWeb,
    SUM(CASE WHEN Status = 'OnHold' THEN 1 ELSE 0 END) AS onHold,
    SUM(CASE WHEN Status = 'onHold' AND AppType = 'MOBILE' THEN 1 ELSE 0 END) AS onHoldMobile,
    SUM(CASE WHEN Status = 'onHold' AND AppType = 'WEB' THEN 1 ELSE 0 END) AS onHoldWeb,
    SUM(CASE WHEN Status = 'Active' OR Status = 'onHold' THEN 1 ELSE 0 END) AS ActiveAndOnHold,
    SUM(CASE WHEN (Status = 'Active' OR Status = 'onHold') AND AppType = 'MOBILE' THEN 1 ELSE 0 END) AS ActiveAndOnHoldMobile,
    SUM(CASE WHEN (Status = 'Active' OR Status = 'onHold') AND AppType = 'WEB' THEN 1 ELSE 0 END) AS ActiveAndOnHoldWeb
FROM events
GROUP BY Task;

我意识到我正在重复计算同样的事情,我应该能够添加部分结果,但老实说,如果不遍历 table 不止一次,我不知道该怎么做.

实际查询还有大约 20 个 SUM,它们是相同数据的组合。查询需要一段时间到 运行(大约两个小时)。我想知道是否有更好的方法来做到这一点。

非常欢迎任何建议。

谢谢

您可以保留中间标志。我怀疑这会加快您的查询速度,但它会使维护更简单:

SELECT Task, COUNT(*) as Total,
        SUM(is_active) AS Active,
        SUM(is_active * is_mobile) AS ActiveMobile,
        . . .
FROM events e CROSS APPLY
     (VALUES (CASE WHEN Status = 'Active' THEN 1 ELSE 0 END),
             (CASE WHEN Status = 'OnHold' THEN 1 ELSE 0 END),
             (CASE WHEN AppType = 'WEB' THEN 1 ELSE 0 END),
             (CASE WHEN AppType = 'MOBILE' THEN 1 ELSE 0 END),
             . . .
     ) v(is_active, is_onhold, is_web, is_mobile)
GROUP BY Task;

如果您的比较实际上比简单的字符串相等更麻烦,这可能会影响性能。

确保您的查询具有完全覆盖索引。这可以带来巨大的不同。确保您的查询计划使用多核。如果您查看查询计划,请查找收集运算符。这与上面的 maxdop 建议有关。考虑使用获取行计数的详细信息子查询。然后另一个查询将您的字段分解为最终结果。

select F1, sum(case when A = 1 then ItemCount else 0 end) SummaryField
from 
(
  select F1, A, count(*) ItemCount
  from T1
  group by F1, A
) T2
group by F1 

如果所有其他方法都失败了,请考虑将聚合结果缓存在 table 中,该 table 仅包含聚合查询的结果集。原来聚合查询可以运行每两个小时。但是查询缓存table会包含更少的记录,查询起来会容易很多。