2013-02-10 57 views
2

让我们假设我们有PostgreSQL的两个表:PostgreSQL的GROUP BY:在另一个MAX选择的列,其中第三列= X

表 “公民”

country_ref citizen_name entry_date 
----------------------------------------------------- 
0    peter   2013-01-14 21:00:00.000 
1    fernando  2013-01-14 20:00:00.000 
0    robert   2013-01-14 19:00:00.000 
3    albert   2013-01-14 18:00:00.000 
2    esther   2013-01-14 17:00:00.000 
1    juan   2013-01-14 16:00:00.000 
3    egbert   2013-01-14 15:00:00.000 
1    francisco  2013-01-14 14:00:00.000 
3    adolph   2013-01-14 13:00:00.000 
2    emilie   2013-01-14 12:00:00.000 
2    jacques   2013-01-14 11:00:00.000 
0    david   2013-01-14 10:00:00.000 

表 “国家”

country_id  country_name country_group 
------------------------------------------- 
0    england  0 
1    spain   0 
2    france   1 
3    germany  1 

现在我想要获取给定country_group的每个国家/地区的“公民”表上最后输入的公民。

我最好的尝试到目前为止,这是查询(我们称之为QUERY_1):

SELECT country_ref, MAX(entry_date) FROM citizens 
LEFT JOIN countries ON country_id = country_ref 
WHERE country_group = 1 GROUP BY country_ref 

输出:

country_ref max 
--------------------------------- 
3    2013-01-14 18:00:00 
2    2013-01-14 17:00:00 

于是我可以这样做:

SELECT citizen_name FROM citizens WHERE (country_ref, entry_date) IN (Query_1) 

.. 。这会给我我要找的输出:albertesther

但我更愿意在单个查询中实现此目的。我想知道是否有可能?

回答

5

这应该是最简单和最快的:

SELECT DISTINCT ON (i.country_ref) 
     i.citizen_name 
FROM citizens i 
JOIN countries o ON o.country_id = i.country_ref 
WHERE o.country_group = 1 
ORDER BY i.country_ref, i.entry_date DESC 

您可以通过简单地将它们添加到列表SELECT返回两个表中的多个列。
SQL Fiddle.

详细信息,链接和解释在这个相关答案:

1

你为什么不干脆:

SELECT citizen_name FROM citizens WHERE (country_ref, entry_date) IN (
    SELECT country_ref, MAX(entry_date) FROM citizens 
    LEFT JOIN countries ON country_id = country_ref 
    WHERE country_group = 1 GROUP BY country_ref 
) 

它可能不是最好的方案,但它取决于许多因素,这是简单的写。

+0

是的,这就是我实际上做到目前为止(参见我写SELECT citizen_name公民WHERE (country_ref,entry_date)IN(Query_1)在我的问题),但我想在一个单一的查询,如果可能的话... – Fracu 2013-02-10 23:24:13

+1

@Francisco:**是**一个查询 – 2013-02-10 23:25:16

+0

对不起,我的意思是说我试图避免嵌套查询或使用或子查询。 – Fracu 2013-02-12 20:27:38

3
SELECT citizen_name, 
     country_ref, 
     entry_date 
from (
    SELECT cit.citizen_name, 
     cit.country_ref, 
     MAX(cit.entry_date) over (partition by cit.country_ref) as max_date, 
     cit.entry_date 
    FROM citizens cit 
    LEFT JOIN countries cou ON cou.country_id = cit.country_ref 
    WHERE cou.country_group = 1 
) t 
where max_date = entry_date 

SQLFiddle演示:http://www.sqlfiddle.com/#!12/50776/1