PostgreSQL'de kategoriye göre maksimum tarih grubuna sahip id nasıl seçilir?


91

Örneğin, kategoriye göre maksimum tarih grubu ile id seçmek istiyorum, sonuç: 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

Bunu PostgreSQL'de nasıl yapacağımı öğrenebilir miyim?


4
PostgreSQL sürümünüzü eklemek her zaman akıllıca olacaktır.
Erwin Brandstetter

Yanıtlar:


145

Bu, DISTINCT ONstandardın Postgres'e özgü bir uzantısı için mükemmel bir kullanım durumudur DISTINCT:

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

Azalan sıralama düzenine dikkat edin. Sütun NULL olabiliyorsa, eklemek isteyebilirsiniz NULLS LAST:

DISTINCT ONbasit ve hızlıdır. Bu ilgili cevapta ayrıntılı açıklama:

Başına birçok satır içeren büyük tablolar categoryiçin alternatif bir yaklaşım düşünün:


Harika görünüyor, ancak bunun her seferinde çalışacağından kesinlikle emin misiniz?
Atherion

@Tixel: Kesinlikle. Daha fazla ayrıntı için bağlantıları izleyin.
Erwin Brandstetter

21

Bunu dene:

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

Bu SQLFiddle'a bakın


1
Rank () pencere işlevini kullanan başka bir seçenek vardır.
Denis de Bernardy

@ user1735921: Tüm sütunları Tablo1'den alacaksınız. Hangisini istersen seçebilirsin.
Himanshu Jansari

16

Başka bir yaklaşım, first_valuepencere işlevini kullanmaktır : http://sqlfiddle.com/#!12/7a145/14

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

... onun önerisinin genellikle uygun indeksler mevcut olduğunda daha iyi performans göstereceğinden şüphelenmeme rağmen.

Üçüncü bir çözüm şudur:

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

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.