多SiteId与多指标场景下,如何正确实现分组COUNT DISTINCT统计?
问题分析与解决方案
问题根源
你遇到的结果不一致问题,核心原因是原查询的日期筛选逻辑放在了CASE语句中,而非WHERE条件里。虽然GROUP BY SiteId会按站点分组统计,但当查询多个站点时,数据库的执行计划可能发生变化(比如采用不同的索引、聚合策略),导致同一站点的统计结果出现偏差。本质上,你需要的是仅统计每个站点下,符合日期范围的去重CodeProfile数量,原逻辑的写法容易引发执行层面的不确定性。
基础解决方案(单指标)
最直接且稳定的写法是先通过WHERE过滤出符合日期和站点条件的数据,再分组统计去重值,逻辑清晰且结果稳定:
SELECT SiteId, COUNT(DISTINCT CodeProfile) AS TotalRecords FROM LogTTHC WHERE SiteId IN (60, 249) AND CreatedReceiveLeve1 >= '2024-01-01' AND CreatedReceiveLeve1 <= '2024-10-01' GROUP BY SiteId;
如果因业务需要(比如要同时统计不符合日期条件的其他指标)必须保留CASE写法,建议显式声明ELSE NULL(和原逻辑等价,但可读性更强),确保分组内的统计逻辑完全独立:
SELECT SiteId, COUNT(DISTINCT CASE WHEN CreatedReceiveLeve1 >= '2024-01-01' AND CreatedReceiveLeve1 <= '2024-10-01' THEN CodeProfile ELSE NULL END) AS TotalRecords FROM LogTTHC WHERE SiteId IN (60, 249) GROUP BY SiteId;
多指标批量查询方案
如果需要一次性查询大量站点和多个统计指标(比如不同日期区间的去重计数),推荐使用条件聚合的方式,既高效又能避免多次查询带来的性能损耗:
SELECT SiteId, -- 统计2024年1-10月的去重记录数 COUNT(DISTINCT CASE WHEN CreatedReceiveLeve1 BETWEEN '2024-01-01' AND '2024-10-01' THEN CodeProfile END) AS TotalRecords_Jan_Oct, -- 统计2024年第三季度的去重记录数 COUNT(DISTINCT CASE WHEN CreatedReceiveLeve1 BETWEEN '2024-07-01' AND '2024-09-30' THEN CodeProfile END) AS TotalRecords_Q3, -- 可根据需求继续添加更多指标 FROM LogTTHC WHERE SiteId IN (60, 249, 101, 305) -- 支持批量站点ID GROUP BY SiteId;
这种写法中,每个指标的统计都基于当前站点的行数据,完全独立于其他站点,不会因查询的站点数量变化导致结果偏差。
内容的提问来源于stack exchange,提问作者navnforfun
相关产品推荐
相关产品推荐

