如何在PostgreSQL中按类别选择最大日期ID?

use*_*043 72 sql postgresql greatest-n-per-group

举个例子,我想按类别选择带有最大日期组的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
Run Code Online (Sandbox Code Playgroud)

我可以在PostgreSQL中知道如何做到这一点吗?

Erw*_*ter 121

这是DISTINCT ON(Postgres标准特定扩展DISTINCT)的完美用例:

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

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

DISTINCT ON最简单快速.本相关答案的详细解释如下:

对于大表,考虑这种替代方法:

性能优化许多每行category:


him*_*056 19

试试这个:

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

看到这个SQLFiddle


Cra*_*ger 13

另一种方法是使用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;
Run Code Online (Sandbox Code Playgroud)

...虽然我怀疑他的建议通常会在适当的索引存在的情况下表现得更好.

第三种解决方案是:

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