Saya melihat banyak orang menggunakan subqueries atau fitur khusus vendor untuk melakukan ini, tetapi saya sering melakukan query seperti ini tanpa subqueries dengan cara berikut. Ia menggunakan SQL standar yang sederhana sehingga harus bekerja di merek RDBMS apa pun.
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 t1tempat tidak ada baris lain yang samaUserId dan lebih besar.
(Saya menempatkan pengidentifikasi "Tanggal" di pembatas karena itu kata yang dilindungi undang-undang.)
Dalam hal jika t1."Date" = t2."Date" , penggandaan muncul. Biasanya tabel memiliki auto_inc(seq)kunci, mis id. Untuk menghindari penggandaan bisa digunakan 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 yang lebih rinci:
Gabung luar mencoba bergabung t1dengan t2. Secara default, semua hasil t1dikembalikan, dan jika ada kecocokan di t2, itu juga dikembalikan. Jika tidak ada kecocokan t2untuk satu baris tertentut1 , maka kueri masih mengembalikan baris t1, dan digunakan NULLsebagai pengganti untuk semuat2 kolom. Begitulah cara kerja gabungan luar secara umum.
Trik dalam kueri ini adalah merancang kondisi pencocokan gabungan sedemikian rupa sehingga t2harus sama userid , dan lebih besar date . Gagasannya adalah jika ada baris t2yang memiliki lebih besar date, maka baris di t1dalamnya dibandingkan dengan tidak bisa menjadi yang terbaik dateuntuk itu userid. Tetapi jika tidak ada kecocokan - yaitu jika tidak ada baris t2dengan yang lebih besar datedari pada baris t1- kita tahu bahwa baris dalamt1 adalah baris dengan baris terbesar dateuntuk yang diberikan userid.
Dalam kasus tersebut (ketika tidak ada kecocokan), kolom t2akan menjadi NULL- bahkan kolom yang ditentukan dalam kondisi gabungan. Jadi itu sebabnya kami menggunakan WHERE t2.UserId IS NULL, karena kami sedang mencari kasus di mana tidak ada baris ditemukan dengan yang lebih besar dateuntuk yang diberikan userid.