【发布时间】:2013-01-20 01:34:59
【问题描述】:
给定以下 4 个表格:
CREATE TABLE events ( id, name )
CREATE TABLE profiles ( id, event_id )
CREATE TABLE donations ( amount, profile_id )
CREATE TABLE event_members( id, event_id, user_id )
我正在尝试获取所有活动的列表,以及任何成员的数量以及任何捐赠的总和。问题是捐赠的总和返回错误(似乎是捐赠的笛卡尔结果 * # of event_members)。
这是 SQL 查询 (Postgres)
SELECT events.name, COUNT(DISTINCT event_members.id), SUM(donations.amount)
FROM events
LEFT OUTER JOIN profiles ON events.id = profiles.event_id
LEFT OUTER JOIN donations ON donations.profile_id = profiles.id
LEFT OUTER JOIN event_members ON event_members.event_id = events.id
GROUP BY events.name
总和(donations.amount)返回 = 实际捐赠总和 * event_members 中的行数。如果我注释掉 count(distinct event_members.id) 和 event_members left outer join,总和是正确的。
编辑:Erwin 为我指出了正确的方向。查询重写为:
选择 events.name, COUNT(DISTINCT event_members.id), 从捐赠中选择(SUM(donations.amount),其中donations.profile_id = profiles.id 和profiles.event_id = events.id 的个人资料)作为total_donations 从事件 左外连接 event_members ON event_members.event_id = events.id GROUP BY events.name【问题讨论】:
-
顺便说一下,将 sum(donations.amount) 更改为 count(distinct Donations.id) 确实会产生正确的捐款数量
-
嗨,刚刚重新排序了您问题中的
create table语句以反映join的顺序。 -
嗨,您可以将自己的解决方案变成一个新的答案(甚至接受它,如果您最喜欢它:)
-
使用
EXPLAIN ANALYZE测试性能。相关的子查询(就像您在解决方案中使用的那样)通常要慢得多。如果在基表中的许多行中结果中只有几行,它仍然可能获胜。
标签: sql postgresql left-join aggregate-functions