获取连接表格列的不同总和

我在这里有一个问题,我希望有一个简单的解决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之前获取结果数量的最佳方法

一步步:

  1. GROUP BY t.attendee_id – 你通常会做一个子查询。

  2. 然后我总结一下票数来得到票数。 效率不是很高,但是被你的要求所迫。 sum(count(*)) OVER ()将聚合函数count(*)包装在窗口函数sum( ... ) OVER ()以得到不那么常见的expression式。

    并且将每个参与者的最低收入加起来以得到没有重复的总和。

    您也可以使用max()avg()而不是min()来获得相同的效果,因为每位与会者的revenue保证与每行相同。

    如果在窗口函数中允许DISTINCT ,这可能会更简单,但是PostgreSQL尚未实现此function。 每个文档 :

    与常规集合函数不同,集合窗口函数不允许在函数参数列表中使用DISTINCTORDER BY

  3. 最后一步是获得一个单一的行。 这可以用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