Đây là vấn đề lớn nhất-n-per-group thường xuyên xuất hiện trên Stack Overflow.
Đây là câu trả lời thông thường của tôi:
select
p.name player,
s.date first_score,
s.points points
from players p
join scores s
on s.player_id = p.id
left outer join scores s2
on s2.player_id = p.id
and s2.date < s.date
where
s2.player_id is null
;
Nói cách khác, đã cho điểm s, hãy cố gắng tìm điểm s2 cho cùng một người chơi, nhưng với một ngày sớm hơn. Nếu không tìm thấy điểm sớm hơn thì s là điểm sớm nhất.
Nhận xét của bạn về cà vạt:Bạn phải có một chính sách để sử dụng cái nào trong trường hợp cà vạt. Một khả năng là nếu bạn sử dụng khóa chính tự động tăng, khóa có giá trị nhỏ nhất là khóa sớm hơn. Xem thuật ngữ bổ sung trong phần nối bên ngoài bên dưới:
select
p.name player,
s.date first_score,
s.points points
from players p
join scores s
on s.player_id = p.id
left outer join scores s2
on s2.player_id = p.id
and (s2.date < s.date or s2.date = s.date and s2.id < s.id)
where
s2.player_id is null
;
Về cơ bản, bạn cần thêm các điều khoản tiebreaker cho đến khi bạn nhận được một cột được đảm bảo là duy nhất, ít nhất là đối với người chơi nhất định. Khóa chính của bảng thường là giải pháp tốt nhất, nhưng tôi đã gặp trường hợp cột khác phù hợp.
Về các nhận xét mà tôi đã chia sẻ với @OMG Ponies, hãy nhớ rằng loại truy vấn này có lợi rất nhiều từ chỉ mục phù hợp.