具有多个左连接的 SQL 重复行
Posted
技术标签:
【中文标题】具有多个左连接的 SQL 重复行【英文标题】:SQL duplicate rows with multiple left joins 【发布时间】:2017-09-18 12:16:12 【问题描述】:我目前面临以下问题: 我有 3 个需要从中获取信息的表,并且这两个连接都是一对多的。由于某种原因,第二次连接创建了行的重复,结果第二次返回值被弄乱了(bb.count 乘以第二次连接行的数量)
SELECT aa.id, sum(bb.count), count(DISTINCT cc.id)
FROM aaaa aa
LEFT JOIN bbbb bb ON bb.aa_id = aa.id
LEFT JOIN cccc cc ON cc.bb_id = bb.id
GROUP BY aa.id
有没有办法在不进行其他查询的情况下获得正确的 bb.count 总和? 在我删除第二个左连接的那一刻,一切都很好,不幸的是,我需要它作为第三个返回值,我无法对它们进行分组而不导致结果中出现重复(某种)行。
假设有
bb1.count = 9
bb2.count = 5
还有两行cc.bb_id = bb1.id
我得到的结果是 23 而不是 14。
【问题讨论】:
最小的工作样本?.. 【参考方案1】:您在上述查询中遇到聚合扇出。
这是因为有
aaa
和 bbb
之间的 1-1 或 1-N 连接
bbb
和 ccc
之间存在 1-N 连接
如果通过 ccc
的连接将它们连接到 M 行,则后一个连接会为存在于 bbb
中的行创建 M
重复项
要修复错误,请将查询拆分为两个 CTE 并连接结果。
WITH agg_bb AS (
SELECT aa.id, sum(bb.count)
FROM aaaa aa
LEFT JOIN bbbb bb ON bb.aa_id = aa.id
GROUP BY aa.id
)
, agg_cc AS (SELECT aa.id, count(DISTINCT cc.id)
FROM aaaa aa
LEFT JOIN bbbb bb ON bb.aa_id = aa.id
LEFT JOIN cccc cc ON cc.bb_id = bb.id
GROUP BY aa.id
)
SELECT * FROM agg_bb JOIN agg_cc USING (id)
一般来说,为了避免扇出,只对一系列连接中最右边关系的列应用聚合操作。如果您发现您正在聚合中间表中的列,请按照我在上面所做的那样拆分查询。只有以下函数在扇出过程中是不变的:COUNT DISTINCT
、MIN
、MAX
【讨论】:
谢谢你,你拯救了我的一天!以上是关于具有多个左连接的 SQL 重复行的主要内容,如果未能解决你的问题,请参考以下文章
MYSQL - 将具有多个重复值的行组合起来,然后删除重复项