获取连接表格列的不同总和
我在这里有一个问题,我希望有一个简单的解决scheme。 我会尽可能简单地做到这一点:
- 一张票属于一个参加者
- 例:
select * from tickets JOIN attendees ON attendee.id = tickets.attendee_id
- 与会者有一个称为“收入”的小数列
也就是说,我需要运行一个查询,返回有关门票的各种信息,包括总收入。 问题是,如果2张门票属于同一个参与者,那么它会将收入计入两次。 我如何才能将与会者的收入总计一次?
我不想使用子查询,因为我的ORM使这很难。 另外一个子查询解决scheme不能缩放,如果我想这样做多个列。
这是我有:
- 1位参与者,收入为100美元
- 两张门票都属于该参与者
Select count(tickets.*) as tickets_count , sum(attendees.revenue) as atendees_revenue from tickets LEFT OUTER JOIN attendees ON attendees.id = tickets.attendee_id;
=>这告诉我, attendees_revenue
是200.我希望它是100.因为在数据库中有一个参与者与existing_revenue为100.我不希望与会者被重复计数。
请让我知道这是否可能。
要得到没有子查询的结果,你必须诉诸高级窗口函数的诡计:
SELECT sum(count(*)) OVER () AS tickets_count ,sum(min(a.revenue)) OVER () AS atendees_revenue FROM tickets t JOIN attendees a ON a.id = t.attendee_id GROUP BY t.attendee_id LIMIT 1;
SQL小提琴。
说明
理解这个关键是查询中事件的顺序 :
集合函数 – >窗口函数 – > DISTINCT – > LIMIT
更多细节在这里:
- 在应用LIMIT之前获取结果数量的最佳方法
一步步:
-
我
GROUP BY t.attendee_id
– 你通常会做一个子查询。 -
然后我总结一下票数来得到票数。 效率不是很高,但是被你的要求所迫。
sum(count(*)) OVER ()
将聚合函数count(*)
包装在窗口函数sum( ... ) OVER ()
以得到不那么常见的expression式。并且将每个参与者的最低收入加起来以得到没有重复的总和。
您也可以使用
max()
或avg()
而不是min()
来获得相同的效果,因为每位与会者的revenue
保证与每行相同。如果在窗口函数中允许
DISTINCT
,这可能会更简单,但是PostgreSQL尚未实现此function。 每个文档 :与常规集合函数不同,集合窗口函数不允许在函数参数列表中使用
DISTINCT
或ORDER BY
。 -
最后一步是获得一个单一的行。 这可以用
DISTINCT
(SQL标准)完成,因为所有行都是相同的。 尽pipe如此,LIMIT 1
会更快。 或者是SQL标准表单FETCH FIRST 1 ROWS ONLY
。
你实际上非常接近,有很多方法可以做到这一点,如果我正确理解你的问题,这应该做到这一点:
SELECT COUNT(*) AS ticketsCount, SUM(DISTINCT attendees.revenue) AS revenueSum FROM tickets LEFT JOIN attendees ON attendees.id = tickets.attendee_id
以前的回答几乎是正确的。 如果收入相同,您只需要做好不同的工作。 如果你的ID有数字types,你可以修复这个很简单:
SELECT COUNT(*) AS ticketsCount, SUM(DISTINCT attendees.id + attendees.revenue) - SUM(DISTINCT attendees.id) AS revenueSum FROM tickets LEFT JOIN attendees ON attendees.id = tickets.attendee_id