Bagaimana cara memilih id dengan grup tanggal maksimal berdasarkan kategori di PostgreSQL?

91

Sebagai contoh, saya ingin memilih id dengan kelompok tanggal max berdasarkan kategori, hasilnya adalah: 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

Bolehkah saya tahu cara melakukan ini di PostgreSQL?

pengguna2412043
sumber
4
Itu selalu bijaksana untuk memasukkan versi PostgreSQL Anda.
Erwin Brandstetter

Jawaban:

145

Ini adalah kasus penggunaan yang sempurna untuk DISTINCT ON- ekstensi khusus Postgres dari standar DISTINCT:

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

Hati-hati dengan urutan menurun. Jika kolomnya bisa NULL, Anda mungkin ingin menambahkan NULLS LAST:

DISTINCT ONsederhana dan cepat. Penjelasan rinci dalam jawaban terkait ini:

Untuk tabel besar dengan banyak baris per categorypertimbangkan pendekatan alternatif:

Erwin Brandstetter
sumber
Kelihatannya bagus, tetapi apakah Anda benar-benar yakin ini dijamin akan berhasil setiap saat?
Atherion
@Tixel: Tentu saja. Ikuti tautan untuk lebih jelasnya.
Erwin Brandstetter
21

Coba yang ini:

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

Lihat SQLFiddle ini

Himanshu Jansari
sumber
1
Ada opsi lain menggunakan fungsi jendela rank ().
Denis de Bernardy
@ user1735921: Anda akan mendapatkan semua kolom dari Tabel1. Anda dapat memilih mana yang Anda inginkan.
Himanshu Jansari
16

Pendekatan lain adalah dengan menggunakan first_valuefungsi jendela: http://sqlfiddle.com/#!12/7a145/14

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

... meskipun saya curiga saran hims056 biasanya akan bekerja lebih baik jika ada indeks yang sesuai.

Solusi ketiga adalah:

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

PILIH ID DARI GRUP tbl OLEH cat HAVING MAX (tanggal)

Tidak penyayang
sumber
2
Ini adalah sintaks ilegal dan tidak menjawab pertanyaan.
Erwin Brandstetter
4
Ini tidak bekerja pada PostgreSQL tetapi bekerja dengan Sqlite
vladaman