在1:n关系中加入并命令来自两个表的不同行

时间:2012-06-07 11:29:37

标签: sql postgresql left-join aggregate-functions

我有一个包含列的数据库表r_event

event_start (date), 
event_stop (date),
insurance_id (integer) 

以及包含列的表r_insurance

insurance_id serial primary key,
insurance_name (text)

每个保险都有几个由insurance_id链接的事件。

我正在努力:
SELECT insurance_id, insurance_name - 每个只有1个,
并按最大 event_stop订购:
ORDER BY event_stop DESC NULLS LAST - ??

实施例

r_insurance (insurance_id, insurance_name)
1 | rca
2 | casco
3 | itp

r_event (insurance_id, event_start, event_stop)
1 | 12.10.2012 | 27.11.2012
1 | 07.05.2012 | 24.06.2012
2 | 21.01.2013 | 14.02.2013

输出应为:

1 | casco -- cause it has the event with the biggest event_stop  
2 | rca   -- cause it has the 1st event_stop after the biggest event_stop  
3 | itc   -- cause it doesn't have events

我编辑了我的初稿,我希望它们按照最大event_stopNULLS LAST的事件排序。

2 个答案:

答案 0 :(得分:2)

SELECT i.insurance_id, i.insurance_name, max(e.event_stop) latest_stop
FROM   r_insurance i
LEFT   JOIN r_event e USING (insurance_id)
GROUP  BY 1, 2
ORDER  BY latest_stop DESC NULLS LAST;

在您的示例中,LEFT JOIN对于避免r_insurance中没有r_event - itc中没有相关行的行是必不可少的。
ORDER BY已成为DESC。此外,NULLS LAST之前没有逗号。

在PostgreSQL 9.1中,主键涵盖SELECT列表中表的所有非聚合列,因此您可以简化(更多详细信息here):

SELECT i.insurance_id, i.insurance_name, max(e.event_stop) latest_stop
FROM   r_insurance i
LEFT   JOIN r_event e USING (insurance_id)
GROUP  BY 1
ORDER  BY latest_stop DESC NULLS LAST;

Demo on sqlfiddle.

答案 1 :(得分:1)

  

“它可以用GROUP BY完成,但我不知道它做了什么以及如何”

Group by采用一种关系并将其划分为具有相同值的所有行的分区。从那里,您将从结果关系中的每个分区获得一行;聚合函数占用每个分区而不是整个分区。你可以制定类似的东西:

SELECT
 insurance_id,
 insurance_name,
 max(stop) max_stop
FROM r_event JOIN r_insurance
 ON r_event.insurance_id = r_insurance.insurance_id
GROUP BY insurance_id, insurance_name
ORDER BY max_stop, NULLS LAST