Postgres新增JOIN导致SUM计算结果翻倍问题咨询
为什么第二个SQL查询的SUM结果是预期值的两倍?
这个问题的核心在于多次同表连接导致的行数膨胀,咱们一步步拆解来看:
先看第一个符合预期的查询
SELECT *, SUM(CASE WHEN "token"."name" = '' THEN 5 ELSE 9 END) AS "n" FROM "word" LEFT OUTER JOIN "token" ON ("word"."id" = "token"."word_id") WHERE ("word"."id" = 1) GROUP BY "word"."id";
当word.id=1的记录左连接token表时,会得到2条结果行:1条token.name为空,1条token.name非空。SUM计算时就是5+9=14,完全符合你的预期。
再看结果翻倍的第二个查询
SELECT *, SUM(CASE WHEN "token"."name" = '' THEN 5 ELSE 9 END) AS "n" FROM "word" LEFT OUTER JOIN "token" ON ("word"."id" = "token"."word_id") INNER JOIN "token" T3 ON ("word"."id" = T3."word_id") WHERE ("word"."id" = 1) GROUP BY "word"."id";
问题就出在连续两次连接同一个token表:
- 第一步:
word左连接token后,得到2条基础行(记为行A:token.name为空;行B:token.name非空)。 - 第二步:用这2条基础行再内连接
token T3(同样匹配word_id=1),而T3里同样有2条对应记录。这时每一条基础行都会和T3的2条记录匹配,最终生成的行数是2×2=4条:- 行A + T3的空值行
- 行A + T3的非空行
- 行B + T3的空值行
- 行B + T3的非空行
- 最后SUM计算时,CASE语句会对这4条行分别求值:
- 行A对应的两条贡献
5+5=10 - 行B对应的两条贡献
9+9=18 - 总和
10+18=28,正好是原预期值的两倍。
- 行A对应的两条贡献
简单来说,第二次连接token表没有额外过滤条件,只是基于word_id匹配,导致左连接后的每条记录都被重复了token表中对应记录的次数,最终SUM相当于把原来的每个值都加了两次,结果自然翻倍。
内容的提问来源于stack exchange,提问作者Paul R
相关产品推荐
相关产品推荐

