具有多个左连接的 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】:

您在上述查询中遇到聚合扇出。

这是因为有

aaabbb 之间的 1-1 或 1-N 连接 bbbccc 之间存在 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 DISTINCTMINMAX

【讨论】:

谢谢你,你拯救了我的一天!

以上是关于具有多个左连接的 SQL 重复行的主要内容,如果未能解决你的问题,请参考以下文章

删除 SQL 中的重复行

左连接返回重复的行

SQL选择一列中具有重复值的所有行

MYSQL - 将具有多个重复值的行组合起来,然后删除重复项

如何在没有任何重复行的情况下连接 cognos 中的两个表?

SQL Server:如果左连接没有结果,则返回占位符/文本[重复]