You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SQL分组统计前去重 优化嵌套GROUP BY实现方案

去重统计优化方案

你不需要写两层GROUP BY,直接用多列参数的COUNT(DISTINCT)聚合就能一步得到结果,写法如下:

SELECT
  Test AS TestName,
  COUNT(DISTINCT Patient, Test, Value) AS Result
FROM patient_test
GROUP BY Test;

这个写法的执行逻辑是:按检测项分组聚合时,自动对「患者+检测项+检测值」三个维度的重复组合去重计数,数据库引擎会在单次聚合扫描中完成所有计算,比嵌套子查询的写法少一层结果集暂存的开销,执行效率更高。


不同写法的注意事项
  • 你之前用的SELECT * FROM patient_test GROUP BY Patient , Test, Value写法存在兼容性风险:在开启ONLY_FULL_GROUP_BY模式的MySQL、或PostgreSQL等严格遵循SQL标准的数据库中,SELECT子句中未出现在GROUP BY里、也未做聚合处理的字段会直接抛出语法错误,返回的未分组字段值也存在不确定性,不建议生产环境使用。
  • 你提到DISTINCT会丢失字段的问题,仅存在于单独用SELECT DISTINCT 列名返回结果的场景;把DISTINCT写在COUNT()聚合函数内部时,只影响计数的去重逻辑,不会限制外层SELECT返回其他业务字段,你可以正常查询patient_test表的其他列,配合对应聚合函数使用即可。
  • 关于视图封装的效率:普通视图本身不存储数据,只是封装了SQL逻辑,查询时还是会展开执行底层语句,不会带来性能提升;如果你的数据库支持物化视图(如PostgreSQL、Oracle),提前把去重后的明细做预计算存储,才会提升高频查询的效率,但需要额外处理数据同步的开销。

扩展:保留全字段的去重明细方案

如果你后续需要用到去重后的完整明细(携带patient_test表所有业务字段),可以用窗口函数实现稳定去重,替代GROUP BY写法:

SELECT * FROM (
  SELECT
    *,
    ROW_NUMBER() OVER (PARTITION BY Patient, Test, Value ORDER BY (SELECT 1)) AS rn
  FROM patient_test
) t
WHERE rn = 1

这个语句会给每一组重复的「患者+检测项+检测值」记录生成行号,仅保留每组第一条数据,所有原表字段都会完整保留,不受SQL_MODE限制,基于这个明细做后续统计也不会出现字段丢失的问题。

上述统计SQL执行后会直接返回你需要的结果:

TestName  | Result
----------------------
Test A    |  2
Test B    |  5
Test C    |  3 

内容的提问来源于stack exchange,提问作者Alberto Sanchez

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.31 06:24:16