具有多个左连接的 SQL 重复行

Rau*_*uno 8 postgresql left-join duplicates

我目前面临以下问题:我需要从中获取信息的 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
Run Code Online (Sandbox Code Playgroud)

有没有办法在没有其他查询的情况下获得正确的 bb.count 总和?我删除第二个左连接的那一刻一切都很好,不幸的是我需要它作为第三个返回值,并且我无法将它们分组而不导致结果重复(排序)行。

可以说有

bb1.count = 9
bb2.count = 5
Run Code Online (Sandbox Code Playgroud)

有 2 行,cc.bb_id = bb1.id 我得到的结果是 23 而不是 14。

Hal*_*Ali 11

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

发生这种情况是因为有

  • aaa&之间的 1-1 或 1-N 连接bbb
  • bbb&之间有一个 1-N 连接ccc

后一个连接M为存在的行创建重复项,bbb如果它们通过连接连接到 M 行ccc

要修复错误,请将查询拆分为两个 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)
Run Code Online (Sandbox Code Playgroud)

一般来说,为了避免扇出,只对一系列连接中最右边关系的列应用聚合操作。如果您发现您正在聚合中间表中的列,请像我上面所做的那样拆分查询。只有以下函数在扇出中是不变的:COUNT DISTINCT, MIN,MAX