SQL按供应商分组统计去重订单ID价格总和的无嵌套查询实现
完全可以在不使用嵌套查询的前提下实现需求,不需要借助FROM、WHERE子句内嵌的子查询/派生表结构,单层级聚合查询就能完成统计。
大部分人刚拿到这个需求,第一反应会写带嵌套的实现:先筛掉同vendor、同order_id的重复行,再按vendor分组算价格总和,写法是这样的:
-- 典型带嵌套的实现,FROM后内嵌了去重子查询 SELECT vendor, SUM(price) FROM ( SELECT DISTINCT vendor, order_id, price FROM orders ) t GROUP BY vendor;
这个写法结果虽然对,但确实用到了嵌套结构,不符合无嵌套的要求。
无嵌套的实现思路
我们可以借助聚合函数的DISTINCT修饰特性,通过简单的数值组合计算绕过嵌套子查询,核心逻辑很简单:
- 选一个远大于表内最大order_id值的整数当基数(比如示例里用10000,只要比实际最大order_id大,就不会出现数值进位冲突)
- 把price和order_id拼成组合值
price * 基数 + order_id,同一个vendor下不同order_id的这个组合值天然是唯一的 - 对组合值做DISTINCT求和,本质就是给每个唯一的order_id只计入一次对应值
- 从组合值总和里扣掉所有distinct order_id的总和,剩下的就是所有唯一order_id对应的price*基数的累计值,再除以基数就能得到最终需要的sum结果
对应的无嵌套SQL如下:
SELECT vendor, (SUM(DISTINCT price * 10000 + order_id) - SUM(DISTINCT order_id)) / 10000 AS sum FROM orders GROUP BY vendor;
效果验证
用你提供的测试数据跑这个查询,结果完全匹配预期:
- nike分组下有两个不同的order_id(1、2),对应价格都是10:组合值distinct求和为
(10*10000+1) + (10*10000+2) = 200003,扣掉distinct order_id的和1+2=3,除以10000得到20,和预期一致 - adidas分组下的两条数据归属同一个order_id3,组合值distinct之后只保留一次
15*10000+3=150003,扣掉distinct order_id的和3,除以10000得到15,完全符合统计规则
注意事项
- 基数的取值必须大于表内order_id的最大值,否则会出现不同(price, order_id)组合因进位生成相同的组合值,导致计算错误。比如如果表内最大order_id是10万,把基数换成1000000就能完全规避冲突
- 这个写法的适用前提和业务需求一致:同一个vendor下,同一个order_id对应的price是固定值,不会出现同一个order_id对应多个不同价格的情况(否则原统计逻辑本身就没有统一口径)
内容的提问来源于stack exchange,提问作者tee
相关产品推荐
相关产品推荐

