获取连接表列的不同总和

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使这很困难.如果我想为多列执行此操作,则子查询解决方案无法扩展.

这就是我所拥有的:

  • 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;
Run Code Online (Sandbox Code Playgroud)

=>这告诉我这attendees_revenue是200.我希望它是100.因为数据库中有一个参与者,其现有的回报为100.我不希望参与者被重复计算.

如果可能,请告诉我.

Erw*_*ter 8

要在没有子查询情况下获得结果,您必须使用高级窗口函数技巧:

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)

SQL小提琴.

说明

理解这一点的关键是查询中的事件序列:

聚合函数 - >窗口函数 - > DISTINCT - > LIMIT

更多细节在这里:

一步步:

  1. GROUP BY t.attendee_id- 你通常在子查询中做.

  2. 然后我总结了计数以获得门票的总数.效率不高,但受到您的要求的限制.聚合函数count(*)包含在window函数中,sum( ... ) OVER ()以得到不常见的表达式:sum(count(*)) OVER ().

    并计算每位与会者的最低收入,以获得没有重复的金额.

    您也可以使用max()avg()代替min()相同的效果,revenue保证每个参与者的每一行都相同.

    如果DISTINCT在窗口函数中允许,这可能更简单,但PostgreSQL还没有实现此功能.每个文件:

    与普通聚合函数不同,聚合窗口函数不允许DISTINCTORDER BY在函数参数列表中使用.

  3. 最后一步是获得一行.这可以用DISTINCT(SQL标准)完成,因为所有行都是相同的.LIMIT 1但会更快.或者是SQL标准表单FETCH FIRST 1 ROWS ONLY.