满足条件时GROUP BY分组,不满足则保留原数据的SQL实现咨询
解决条件分组:仅当分组数量>2时才分组,否则保留全部记录
嘿,我来帮你捋清楚这个问题!你的需求很明确:对chk分组,当该组的记录数超过2条时,只保留该组的一条记录(按chk, chk2, chk3聚合);如果组内记录数≤2,就原样保留所有条目。
问题分析
从你的示例数据来看,chk=2的组有3条记录,所以最终只留一条;chk=3有2条、chk=5有1条,这些都全部保留。你之前的SQL写法存在两个问题:一是GROUP BY子句里不能直接使用COUNT(*)这类聚合函数;二是CASE语句里返回多列的语法是错误的,GROUP BY需要明确的单列或表达式。
解决方案1:用窗口函数(推荐,简洁高效)
窗口函数可以帮我们先计算每个chk组的总记录数,再根据这个数量决定如何输出:
WITH chk_group_counts AS ( SELECT *, -- 计算当前chk组的总记录数 COUNT(*) OVER (PARTITION BY chk) AS group_size FROM db_name ) SELECT DISTINCT -- 当组大小>2时,取该组(chk,chk2,chk3)分组下的最小id;否则保留原id CASE WHEN group_size > 2 THEN MIN(id) OVER (PARTITION BY chk, chk2, chk3) ELSE id END AS id, chk, chk2, chk3 FROM chk_group_counts ORDER BY id;
解决方案2:用子查询+UNION ALL(兼容旧版本SQL)
如果你的数据库不支持窗口函数,可以用子查询统计分组数量,再分两种情况合并结果:
-- 先获取每个chk组的记录数 WITH chk_groups AS ( SELECT chk, COUNT(*) AS group_size FROM db_name GROUP BY chk ) -- 保留组大小≤2的所有记录 SELECT t.id, t.chk, t.chk2, t.chk3 FROM db_name t JOIN chk_groups g ON t.chk = g.chk WHERE g.group_size <= 2 UNION ALL -- 对组大小>2的组,按chk,chk2,chk3分组取一条记录(这里取最小id) SELECT MIN(t.id) AS id, t.chk, t.chk2, t.chk3 FROM db_name t JOIN chk_groups g ON t.chk = g.chk WHERE g.group_size > 2 GROUP BY t.chk, t.chk2, t.chk3 -- 最后按id排序,和示例输出一致 ORDER BY id;
补充说明
- 两种方案都能实现你的需求,窗口函数的写法更简洁,性能也更好(只需要扫描一次表)。
- 如果你不想取最小id,可以换成
MAX(id)或者其他聚合逻辑,比如取最新的记录,只要调整对应的聚合函数即可。
内容的提问来源于stack exchange,提问作者R.Cremona
相关产品推荐
相关产品推荐

