Rya*_*ick 29 sql postgresql aggregate-functions left-join
我有3张桌子:
users(id, account_balance)
grocery(user_id, date, amount_paid)
fishmarket(user_id, date, amount_paid)
Run Code Online (Sandbox Code Playgroud)
对于具有不同日期和金额的相同user_id,两个fishmarket
和grocery
表可能有多次出现,或者对于任何给定用户都没有任何内容.当我尝试以下查询时:
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
Run Code Online (Sandbox Code Playgroud)
它会产生不正确的结果:"1", "12", "12"
.
但是,当我尝试LEFT JOIN
只有一个表时,它会产生正确的结果,无论是访问grocery
还是fishmarket
访问"1", "3", "4"
.
我在这做错了什么?
我正在使用PostgreSQL 9.1.
Erw*_*ter 48
连接从左到右处理(除非括号另有规定).如果你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;
Run Code Online (Sandbox Code Playgroud)
要查找一个或几个用户的聚合值,像@Vince提供的相关子查询 就可以了.对于整个表或其主要部分,聚合n表并连接到结果一次(更高效).这样,我们在外部查询中也不需要另一个.GROUP BY
小智 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
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
15690 次 |
最近记录: |