Saya melihat banyak orang menggunakan subkueri atau fungsi jendela lain untuk melakukan ini, tetapi saya sering melakukan kueri semacam ini tanpa subkueri dengan cara berikut. Ini menggunakan SQL standar yang sederhana sehingga dapat berfungsi di semua merek RDBMS.
SELECT t1.*
FROM mytable t1
LEFT OUTER JOIN mytable t2
ON (t1.UserId = t2.UserId AND t1."Date" < t2."Date")
WHERE t2.UserId IS NULL;
Dengan kata lain:ambil baris dari t1
di mana tidak ada baris lain dengan UserId
yang sama dan Tanggal yang lebih besar.
(Saya meletakkan pengenal "Tanggal" di pembatas karena ini adalah kata yang dicadangkan SQL.)
Jika t1."Date" = t2."Date"
, penggandaan muncul. Biasanya tabel memiliki auto_inc(seq)
kunci, mis. id
.Untuk menghindari penggandaan dapat digunakan sebagai berikut:
SELECT t1.*
FROM mytable t1
LEFT OUTER JOIN mytable t2
ON t1.UserId = t2.UserId AND ((t1."Date" < t2."Date")
OR (t1."Date" = t2."Date" AND t1.id < t2.id))
WHERE t2.UserId IS NULL;
Komentar ulang dari @Farhan:
Berikut penjelasan lebih detailnya:
Gabungan luar mencoba bergabung dengan t1
dengan t2
. Secara default, semua hasil t1
dikembalikan, dan jika ada kecocokan di t2
, itu juga dikembalikan. Jika tidak ada kecocokan di t2
untuk baris tertentu t1
, maka kueri masih mengembalikan baris t1
, dan menggunakan NULL
sebagai pengganti untuk semua t2
kolom. Begitulah cara kerja outer join secara umum.
Trik dalam kueri ini adalah mendesain kondisi pencocokan gabungan sedemikian rupa sehingga t2
harus cocok dengan sama userid
, dan lebih besar date
. Idenya adalah jika ada baris di t2
yang memiliki date
yang lebih besar , lalu baris di t1
itu dibandingkan dengan tidak bisa jadilah date
terbesar untuk userid
itu . Tetapi jika tidak ada kecocokan -- yaitu jika tidak ada baris di t2
dengan date
yang lebih besar daripada baris di t1
-- kita tahu bahwa baris dalam t1
adalah baris dengan date
terbesar untuk userid
yang diberikan .
Dalam kasus tersebut (bila tidak ada kecocokan), kolom t2
akan menjadi NULL
-- bahkan kolom yang ditentukan dalam kondisi join. Jadi itu sebabnya kami menggunakan WHERE t2.UserId IS NULL
, karena kami sedang mencari kasus di mana tidak ada baris yang ditemukan dengan date
greater yang lebih besar untuk userid
yang diberikan .