2009-06-18 45 views
6

Điều tôi có cơ bản là một vấn đề được giải quyết dễ dàng với nhiều bảng, nhưng tôi chỉ có một bảng duy nhất để thực hiện.SQL - SELECT MAX() và trường đi kèm

Hãy xem xét các bảng cơ sở dữ liệu sau

UserID UserName EmailAddress   Source 
3K3S9 Ben  [email protected]  user 
SF13F Harry [email protected] 3rd_party 
SF13F Harry [email protected] user 
76DSA Lisa  [email protected]  user 
OL39F Nick  [email protected] 3rd_party 
8F66S Stan  [email protected]  user 

tôi cần phải chọn tất cả các lĩnh vực, nhưng người duy nhất mỗi người dùng một lần cùng với một trong những địa chỉ email của họ (các "lớn nhất", một được xác định bởi MAX (chức năng)). Đây là kết quả sau khi tôi ...

UserID UserName EmailAddress   Source 
3K3S9 Ben  [email protected]  user 
SF13F Harry lh[email protected] 3rd_party 
76DSA Lisa  [email protected]  user 
OL39F Nick  [email protected] 3rd_party 
8F66S Stan  [email protected]  user 

Như bạn có thể thấy, "Harry" chỉ hiển thị một lần với địa chỉ email của mình "cao nhất" các correcponding "nguồn"

Hiện nay những gì đang xảy ra là rằng chúng tôi đang nhóm trên UserID, UserName và sử dụng MAX() cho EmailAddress và Source, nhưng tối đa của hai trường đó không luôn khớp nhau, chúng cần phải từ cùng một bản ghi.

Tôi đã thử một quy trình khác bằng cách tự mình tham gia bảng, nhưng tôi chỉ quản lý để có được địa chỉ email chính xác chứ không phải "nguồn" tương ứng cho địa chỉ đó.

Bất kỳ trợ giúp sẽ được đánh giá như tôi đã dành quá dài cố gắng giải quyết này đã :)

+0

Bạn có cột bổ sung có khóa chính được xác định không? Cặp duy nhất (UserId, EmailAddress) có độc đáo không? –

Trả lời

7

Nếu bạn đang ở trên SQL Server 2005 hoặc cao hơn,

SELECT UserID, UserName, EmailAddress, Source 
FROM (SELECT UserID, UserName, EmailAddress, Source, 
       ROW_NUMBER() OVER (PARTITION BY UserID 
            ORDER BY EmailAddress DESC) 
        AS RowNumber 
     FROM MyTable) AS a 
WHERE a.RowNumber = 1 

Dĩ nhiên có nhiều cách để thực hiện tác vụ tương tự mà không có các hàm xếp hạng (SQL-Standard) như ROW_NUMBER, mà SQL Server chỉ thực hiện từ năm 2005 - bao gồm các truy vấn phụ thuộc lồng nhau và kết nối tự trái với ON bao gồm '>' vàThủ thuật- nhưng các hàm xếp hạng làm cho mã có thể đọc được và (theo lý thuyết) cũng có thể được tối ưu hóa bởi SQL Server Engine.

Edit: this article là một hướng dẫn tốt đẹp trên bảng xếp hạng, nhưng nó sử dụng RANK trong các ví dụ thay vì ROW_NUMBER (hoặc chức năng xếp hạng khác, DENSE_RANK) - sự khác biệt quan trọng khi có "quan hệ" giữa hàng nhóm trong cùng một phân vùng theo các tiêu chí đặt hàng. this post thực hiện tốt công việc giải thích sự khác biệt.

+0

Rất thú vị Alex, tôi sẽ nghiên cứu về các tính năng này. – tekBlues

+0

Điều này chắc chắn hoạt động rất tốt ... nhưng tôi không hiểu cú pháp>. Nippysaurus

+0

Đã chỉnh sửa câu trả lời của tôi để thêm URL vào hai hướng dẫn ngắn, tốt về chức năng xếp hạng - HTH! –

5
select distinct * from table t1 
where EmailAddress = 
(select max(EmailAddress) from table t2 
where t1.userId = t2.userId) 
+0

Cần lưu ý rằng điều này thường có thể thực hiện nhanh hơn câu trả lời được chấp nhận, đặc biệt nếu có chỉ mục trên {userid, EmailAddress DESC} trên t2 –

0
select distinct 
    * 
from  
    SomeTable a 
inner join (
    select max(emailAddress), userId 
    from 
    SomeTable 
    group by 
    userId 
) b on a.emailAddress = b.emailAddress and a.userId = b.userId 
+0

Tôi sẽ hạnh phúc hơn nếu điều kiện BẬT bao gồm a.userID = b.userID cũng như địa chỉ email. –

+0

Đúng, nó làm cho nó cụ thể hơn và tránh các vấn đề tiềm ẩn. Tôi đã chỉnh sửa câu trả lời của mình để phản ánh điều này. –

0

Tôi nghĩ rằng tôi có một giải pháp đó là khác biệt so với những người đã đề xuất:

 
select * 
from foo 
where id = (
    select id 
    from foo F 
    where F.bar = foo.bar 
    order by F.baz 
    limit 1 
) 

này cung cấp cho bạn tất cả các hồ sơ foo rằng có baz lớn nhất so với hồ sơ foo khác với thanh tương tự.

Các vấn đề liên quan