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ừ t1nơi không có hàng nào khác tồn tại cùng ngày UserIdvà 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 t1vớ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 t2cho một hàng nhất định t1, thì truy vấn vẫn trả về hàng đó t1và sử dụng NULLlàm trình giữ chỗ cho tất cả các t2cộ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 t2phả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 datecho đ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 t2với hàng lớn datehơn hàng trong t1- chúng ta biết rằng hàng trong đó t1là hàng có giá trị lớn nhất datecho hàng đã cho userid.
Trong những trường hợp đó (khi không có kết quả khớp), các cột t2sẽ 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 datecho trao userid.