Tôi thấy nhiều người sử dụng các truy vấn con hoặc các tính năng dành riêng cho nhà cung cấp để thực hiện việc này, nhưng tôi thường thực hiện loại truy vấn này mà không có truy vấn con theo cách sau. Nó sử dụng SQL đơn giản, chuẩn để nó hoạt động trong bất kỳ thương hiệu RDBMS nào.
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;
Nói cách khác: tìm nạp hàng từ t1
nơi không có hàng nào khác tồn tại cùng ngày UserId
và ngày lớn hơn.
(Tôi đặt mã định danh "Ngày" trong các dấu phân cách vì đó là từ dành riêng cho SQL.)
Trong trường hợp nếu t1."Date" = t2."Date"
, nhân đôi xuất hiện. Các bảng thường có auto_inc(seq)
khóa, vd id
. Để tránh nhân đôi có thể được sử dụng như sau:
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;
Nhận xét lại từ @Farhan:
Đây là một lời giải thích chi tiết hơn:
Một nỗ lực tham gia bên ngoài để tham gia t1
với t2
. Theo mặc định, tất cả các kết quả t1
được trả về và nếu có kết quả khớp t2
, nó cũng được trả về. Nếu không có kết quả trùng khớp t2
cho một hàng nhất định t1
, thì truy vấn vẫn trả về hàng đó t1
và sử dụng NULL
làm trình giữ chỗ cho tất cả các t2
cột. Đó chỉ là cách thức tham gia bên ngoài nói chung.
Thủ thuật trong truy vấn này là thiết kế điều kiện khớp của tham gia sao cho t2
phải khớp như nhau userid
và lớn hơn date
. Ý tưởng là nếu một hàng tồn tại trong t2
đó có lớn hơn date
, thì hàng trong t1
đó được so sánh với không thể là lớn nhất date
cho điều đó userid
. Nhưng nếu không có kết quả khớp - tức là nếu không có hàng nào tồn tại t2
với hàng lớn date
hơn hàng trong t1
- chúng ta biết rằng hàng trong đó t1
là hàng có giá trị lớn nhất date
cho hàng đã cho userid
.
Trong những trường hợp đó (khi không có kết quả khớp), các cột t2
sẽ là NULL
- ngay cả các cột được chỉ định trong điều kiện nối. Vì vậy, đó là lý do chúng tôi sử dụng WHERE t2.UserId IS NULL
, bởi vì chúng tôi đang tìm kiếm các trường hợp không có hàng đã được tìm thấy với một lớn hơn date
cho trao userid
.