2010-04-08 27 views
9

Với ví dụ dữ liệu sau:SQL Tham gia để chỉ các câu đố hàng tối đa

Users 
+--------------------------------------------------+ 
| ID | First Name | Last Name | Network Identifier | 
+--------------------------------------------------+ 
| 1 | Billy  | O'Neal | bro4    | 
+----+------------+-----------+--------------------+ 
| 2 | John  | Skeet  | jsk1    | 
+----+------------+-----------+--------------------+ 

Hardware 
+----+-------------------+---------------+ 
| ID | Hardware Name  | Serial Number | 
+----------------------------------------+ 
| 1 | Latitude E6500 | 5555555  | 
+----+-------------------+---------------+ 
| 2 | Latitude E6200 | 2222222  | 
+----+-------------------+---------------+ 

HardwareAssignments 
+---------+-------------+-------------+ 
| User ID | Hardware ID | Assigned On | 
+-------------------------------------+ 
| 1  | 1   | April 1  | 
+---------+-------------+-------------+ 
| 1  | 2   | April 10 | 
+---------+-------------+-------------+ 
| 2  | 2   | April 1  | 
+---------+-------------+-------------+ 
| 2  | 1   | April 11 | 
+---------+-------------+-------------+ 

Tôi muốn viết một truy vấn SQL mà sẽ cung cấp cho các kết quả sau:

+--------------------+------------+-----------+----------------+---------------+-------------+ 
| Network Identifier | First Name | Last Name | Hardware Name | Serial Number | Assigned On | 
+--------------------------------------------------------------------------------------------+ 
| bro4    | Billy  | O'Neal | Latitude E6200 | 2222222  | April 10 | 
+--------------------+------------+-----------+----------------+---------------+-------------+ 
| jsk1    | John  | Skeet  | Latitude E6500 | 5555555  | April 11 | 
+--------------------+------------+-----------+----------------+---------------+-------------+ 

rắc rối của tôi là rằng ngày "Chỉ định" tối đa cho mỗi người dùng cần phải được chọn cho mỗi người dùng cá nhân và được sử dụng cho việc tham gia thực tế ...

Có cách nào thông minh thực hiện điều này trong SQL không?

+2

Vì vậy, bạn đã có máy tính xách tay cũ của Jon Skeet? Kewl! – APC

+1

@APC: Vâng! Công ty nghĩ rằng ông đã dành quá nhiều thời gian trên StackOverflow ... :) –

Trả lời

9
SELECT U.NetworkIdentifier, U.FirstName, U.LastName, 
     H.HardwareName, H.SerialNumber 
    FROM (SELECT UserID, MAX(AssignedOn) LastAssignment 
      FROM HardwareAssignments 
     GROUP BY UserID) AS T 
    JOIN HardwareAssignments AS HA 
     ON HA.UserId = T.UserID AND HA.AssignedOn = T.LastAssignment 
    JOIN Users AS U ON U.ID = HA.UserID 
    JOIN Hardware AS H ON H.ID = HA.HardwareID 
ORDER BY U.NetworkIdentifier; 

Sự khác biệt giữa câu trả lời này và câu trả lời của Justin Niessner là nơi truy vấn con xuất hiện; ở đây, tôi đã tạo nó trong mệnh đề FROM. Điều này khá nhiều đảm bảo rằng nó được thực hiện một lần. Khi có một truy vấn con tương quan trong mệnh đề WHERE như trong câu trả lời của Justin, có thể là trình tối ưu hóa sẽ thực thi truy vấn con một lần cho mỗi hàng - điều này đắt hơn khi các bảng lớn. Một trình tối ưu hóa thực sự tốt có thể làm phẳng mọi thứ để hai cái tương đương nhau.

+0

+1 Nếu OP có thể làm phiên bản này hoạt động, nó sẽ hoạt động tốt hơn nhiều so với bài viết của tôi (cho tập dữ liệu lớn ... và miễn là trình tối ưu hóa truy vấn không làm phẳng truy vấn của tôi để làm việc theo cách này). –

+0

@Justing Niessner: Đã chuyển câu trả lời được chấp nhận cho câu trả lời này dựa trên nhận xét ở trên. Xin vui lòng không mang nó cá nhân :) –

+0

+1 Thử nghiệm này một thời gian ngắn, rất lớn. Tuy nhiên cần lưu ý rằng truy vấn tương quan có thể hoạt động tốt hơn nếu truy vấn bên ngoài có chọn lọc cao và bảng rất lớn (mặc dù sau đó dễ dàng cải thiện truy vấn trên bằng cách lặp lại tiêu chí lựa chọn trên truy vấn bên trong). – Unreason

8
select * from Users as u 
inner join HardwareAssignments as ha 
    on u.id = ha.userid 
inner join Hardware as h 
    on uh.hardwareid = h.id 
where ha.AssignedOn = (select max(assignedon) 
         from HardwareAssignments as ha2 
         where ha.userid = ha2.userid) 

Điều đó có thể giúp bạn gần gũi. Không chắc chắn nếu nó chính xác.

+0

+1 Đánh bại tôi với nó :) – Unreason

+0

Điều chỉnh các cột theo nhu cầu của bạn, nhưng phần quan trọng của giải pháp là truy vấn phụ. –

+0

Doh! * Bill cảm thấy một chút câm bây giờ –

0

Sử dụng nhóm theo và tối đa để lọc kết quả của phép nối.

+0

Điều đó chỉ trả về một hàng. Tôi cần một hàng cho mỗi người dùng. –