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年

回答:


141

これは、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;

ソート順の降順に注意してください。列が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 2013年

@ user1735921:Table1からすべての列を取得します。あなたはあなたが望むものを選ぶことができます。
ひまんしゅじゃんさり

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の提案は、適切なインデックスが存在する場合、通常はパフォーマンスが向上すると思います。

3番目の解決策は次のとおりです。

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.