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

MySQL中无需子查询,结合DISTINCT实现SUM/GROUP_CONCAT聚合可行吗?

MySQL中聚合函数结合DISTINCT的实现方案

嗨,我来帮你理清这个问题!首先明确说:MySQL完全支持把SUM、GROUP_CONCAT这类聚合函数和DISTINCT结合使用,比如SUM(DISTINCT price)或者GROUP_CONCAT(DISTINCT title)都是合法且常用的语法。不过你这个场景的核心难点不是单纯的结合DISTINCT,而是多表关联产生的笛卡尔积会搞乱聚合结果——直接把选项表和受益人表JOIN后,每条选项会和每个受益人配对,生成大量重复行,最终算出来的总价会是实际值的好几倍,拼接的列表也会充满重复项。

那回到你的核心需求:不用子查询的单条SQL能不能实现?说实话,严格意义上完全不用子查询(包括派生表)的话,很难完美得到你想要的结果,因为笛卡尔积的问题没法彻底规避。不过如果可以接受用派生表(这算是子查询的一种,但很多时候被视为单查询的一部分,代码也更清晰),那有非常优雅的解决方案:

SELECT 
    op.id,
    opt.options,
    opt.options_price,
    ben.beneficiaries
FROM 
    order_product op
JOIN (
    SELECT 
        order_product_id,
        GROUP_CONCAT(title ORDER BY id) AS options,
        SUM(price) AS options_price
    FROM order_product_options
    GROUP BY order_product_id
) opt ON op.id = opt.order_product_id
JOIN (
    SELECT 
        order_product_id,
        GROUP_CONCAT(name ORDER BY id) AS beneficiaries
    FROM order_product_beneficiary
    GROUP BY order_product_id
) ben ON op.id = ben.order_product_id;

这个思路很简单:先分别对选项表和受益人表按order_product_id聚合,得到每个订单产品对应的选项列表、总价,以及受益人列表,再把这些聚合结果和order_product表关联起来。这样完全避免了笛卡尔积的问题,运行后就能得到你想要的结果:

  • id: 1
  • options: option1,option2,option3,option3
  • options_price: 9
  • beneficiaries: mark,jack,jack

如果你真的坚持完全不使用任何子查询,那只能用MySQL的用户变量做一些hack操作,但这种方法代码晦涩,而且在不同MySQL版本中可能有行为差异,绝对不推荐在生产环境使用。

最后再补充几个聚合函数结合DISTINCT的基础用法,方便你理解:

  • 计算不重复的价格总和:SUM(DISTINCT price)
  • 拼接去重后的选项名称:GROUP_CONCAT(DISTINCT title)

这些语法在日常开发中都很实用,可以根据需求灵活搭配。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:46:22