我有三张table:
users(id, account_balance)
grocery(user_id, date, amount_paid)
fishmarket(user_id, date, amount_paid)
字符串fishmarket
和grocery
两个表都可能在同一个user_id中多次出现,但日期和支付金额不同,或者对于任何给定的用户都没有任何内容。当我尝试以下查询时:
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
时,它会为grocery
或fishmarket
访问产生正确的结果,即"1", "3", "4"
。
我做错什么了?
我用的是PostgreSQL 9.1。
4条答案
按热度按时间insrf1ej1#
从左到右处理联接(除非括号另有说明)。如果您
LEFT JOIN
(或仅JOIN
,类似效果)一个用户购买三个杂货,您将获得3行(1 x 3)。如果您为同一用户加入4个fishmarkets,则会得到12个(3 x 4)行,* 乘以 * 结果中的前一个计数,而不是像你希望的那样,* 加上 *。从而使杂货店和鱼市的访问量成倍增加。
你可以让它像这样工作:
字符串
为了获得一个或几个用户的聚合值,* 相关子查询 * like @Vince provided就可以了。对于整个表或它的主要部分,聚合n个表并连接到结果 * 一次 (更)有效。这样,我们也不需要在外部查询中使用另一个
GROUP BY
。grocery_visits
和fishmarket_visits
是*NULL
,用于在各自的表中没有任何相关条目的用户。如果您需要0
(或任何任意数字),请在外部SELECT
中使用COALESCE
**:型
drkbr07n2#
对于您的原始查询,如果您去掉group by以查看预分组的结果,您将看到为什么要创建接收的计数。
也许下面的查询利用子查询将实现您的预期结果:
字符串
dnph8jn43#
这是因为当用户表连接到杂货表时,有3条记录匹配。然后这3条记录中的每一条都与fishmarket中的4条记录匹配,产生12条记录。您需要子查询来获得您要查找的内容。
trnvg8h34#
字符串
上面还将允许您根据需要添加其他标准