两个SQL LEFT JOINS产生不正确的结果

时间:2012-09-17 17:07:51

标签: sql postgresql left-join aggregate-functions

我有3张桌子:

users(id, account_balance)
grocery(user_id, date, amount_paid)
fishmarket(user_id, date, amount_paid)

对于同一个user_id,fishmarketgrocery表可能会多次出现,其中包含不同的日期和金额,或者对于任何给定的用户都没有任何内容。 当我尝试以下查询时:

SELECT
     t1."id" AS "User ID",
     t1.account_balance AS "Account Balance",
     count(t2.user_id) AS "# of grocery visits",
     count(t3.user_id) AS "# of fishmarket visits"
FROM users t1
LEFT OUTER JOIN grocery t2 ON (t2.user_id=t1."id") 
LEFT OUTER JOIN fishmarket t3 ON (t3.user_id=t1."id") 
GROUP BY t1.account_balance,t1.id
ORDER BY t1.id

结果不正确:"1", "12", "12" 但是,当我尝试LEFT JOIN只有一个表格时,它会为groceryfishmarket次访问产生正确的结果,即"1", "3", "4"

我在这里做错了什么?
我正在使用PostgreSQL 9.1。

3 个答案:

答案 0 :(得分:45)

从左到右处理联接(除非括号另有规定)。如果您LEFT JOIN(或仅JOIN(类似的效果)三个杂货给一个用户,您将获得3行( 1 x 3 )。如果您为同一个用户加入4个鱼市,则会得到12( 3 x 4 )行,乘以结果中的先前计数,而不是添加

它应该像这样工作:

SELECT u.id
     , u.account_balance
     , g.grocery_visits
     , f.fishmarket_visits
FROM   users u
LEFT   JOIN (
   SELECT user_id, count(*) AS grocery_visits
   FROM   grocery
   GROUP  BY user_id
   ) g ON g.user_id = u.id
LEFT   JOIN (
   SELECT user_id, count(*) AS fishmarket_visits
   FROM   fishmarket
   GROUP  BY user_id
   ) f ON f.user_id = u.id
ORDER  BY u.id;

要查找一个或几个用户的汇总值,相关子查询 like @Vince provided就可以了。对于整个表或其主要部分,聚合n表并加入结果一次会(更高)。这样,我们在外部查询中也不需要另外GROUP BY

答案 1 :(得分:8)

对于您的原始查询,如果您带走该组以查看预先分组的结果,您将看到为什么您的接收计数已创建。

使用子查询的以下查询可能会实现您的预​​期结果:

SELECT
 t1."id" AS "User ID",
 t1.account_balance AS "Account Balance",
 (SELECT count(*) FROM grocery     t2 ON (t2.user_id=t1."id")) AS "# of grocery visits",
 (SELECT count(*) FROM fishmarket  t3 ON (t3.user_id=t1."id")) AS "# of fishmarket visits"
FROM users t1
ORDER BY t1.id

答案 2 :(得分:2)

这是因为当用户表连接到杂货店表时,有3条记录匹配。然后,这三个记录中的每一个与fishmarket中的4个记录匹配,产生12个记录。您需要子查询才能获得所需内容。