如何在PostgreSQL中按类别选择具有最大日期分组的ID?


88

例如,我想按类别选择具有最大日期分组的ID,结果是:7,2,6

id  category  date
1   a         2013-01-01
2   b         2013-01-03
3   c         2013-01-02
4   a         2013-01-02
5   b         2013-01-02
6   c         2013-01-03
7   a         2013-01-03
8   b         2013-01-01
9   c         2013-01-01

我可以在PostgreSQL中做到这一点吗?


4
包括您的PostgreSQL版本总是明智的。
Erwin Brandstetter 2013年

Answers:


141

这是DISTINCT ON(Postgres对standard的特定扩展DISTINCT)的理想用例:

SELECT DISTINCT ON (category)
       id  -- , category, date -- add any other column (expression) from the same row
FROM   tbl
ORDER  BY category, "date" DESC;

小心降序排列。如果列可以为NULL,则可能要添加NULLS LAST

DISTINCT ON最简单快捷。此相关答案中的详细说明:

对于大型表,请考虑以下替代方法:

每行许多行的性能优化category


看起来不错,但您绝对确定可以保证每次都能正常工作吗?
2015年

@Tixel:绝对。请点击链接以获取更多详细信息。
Erwin Brandstetter,2015年

21

试试这个:

SELECT t1.* FROM Table1 t1
JOIN 
(
   SELECT category, MAX(date) AS MAXDATE
   FROM Table1
   GROUP BY category
) t2
ON T1.category = t2.category
AND t1.date = t2.MAXDATE

看到这个SQLFiddle


1
使用rank()窗口函数还有另一个选项。
Denis de Bernardy

@ user1735921:您将从Table1获得所有列。您可以选择任何一个。
Himanshu Jansari

15

另一种方法是使用first_value窗口函数:http : //sqlfiddle.com/#!12/7a145/14

SELECT DISTINCT
  first_value("id") OVER (PARTITION BY "category" ORDER BY "date" DESC) 
FROM Table1
ORDER BY 1;

...尽管我怀疑hims056的建议通常会在存在适当索引的情况下表现更好。

第三种解决方案是:

SELECT
  id
FROM (
  SELECT
    id,
    row_number() OVER (PARTITION BY "category" ORDER BY "date" DESC) AS rownum
  FROM Table1
) x
WHERE rownum = 1;

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.