Bin*_*gic 5 sql postgresql aggregate-functions duplicate-removal window-functions
我在这里有一个问题,我希望有一个简单的解决方案.我会尝试尽可能简单:
select * from tickets JOIN attendees ON attendee.id = tickets.attendee_id
Run Code Online (Sandbox Code Playgroud)
也就是说,我需要运行一个查询,返回有关票证的各种信息,包括总收入.问题是,如果2张门票属于同一位与会者,则会将其收入计入两次.如何仅将与会者收入相加一次?
我不想使用子查询,因为我的ORM使这很困难.如果我想为多列执行此操作,则子查询解决方案无法扩展.
这就是我所拥有的:
Select count(tickets.*) as tickets_count
, sum(attendees.revenue) as atendees_revenue
from tickets LEFT OUTER JOIN attendees ON attendees.id = tickets.attendee_id;
Run Code Online (Sandbox Code Playgroud)
=>这告诉我这attendees_revenue是200.我希望它是100.因为数据库中有一个参与者,其现有的回报为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;
Run Code Online (Sandbox Code Playgroud)
理解这一点的关键是查询中的事件序列:
聚合函数 - >窗口函数 - > DISTINCT - > LIMIT
更多细节在这里:
一步步:
我GROUP BY t.attendee_id- 你通常在子查询中做.
然后我总结了计数以获得门票的总数.效率不高,但受到您的要求的限制.聚合函数count(*)包含在window函数中,sum( ... ) OVER ()以得到不常见的表达式:sum(count(*)) OVER ().
并计算每位与会者的最低收入,以获得没有重复的金额.
您也可以使用max()或avg()代替min()相同的效果,revenue保证每个参与者的每一行都相同.
如果DISTINCT在窗口函数中允许,这可能更简单,但PostgreSQL还没有实现此功能.每个文件:
与普通聚合函数不同,聚合窗口函数不允许
DISTINCT或ORDER BY在函数参数列表中使用.
最后一步是获得一行.这可以用DISTINCT(SQL标准)完成,因为所有行都是相同的.LIMIT 1但会更快.或者是SQL标准表单FETCH FIRST 1 ROWS ONLY.
| 归档时间: |
|
| 查看次数: |
6329 次 |
| 最近记录: |