2009-06-26 38 views
45

Tôi đang tạo mô-đun bảng trạng thái cho nhóm dự án của mình. Bảng trạng thái cho phép người dùng đặt trạng thái của họ là vào hoặc ra và họ cũng có thể cung cấp ghi chú. Tôi đã lên kế hoạch về lưu trữ tất cả các thông tin trong một bảng duy nhất ... và ví dụ về các dữ liệu sau:Tạo truy vấn SQL để truy xuất các bản ghi gần đây nhất

Date    User   Status Notes 
------------------------------------------------------- 
1/8/2009 12:00pm B.Sisko  In  Out to lunch  
1/8/2009 8:00am B.Sisko  In 
1/7/2009 5:00pm B.Sisko  In  
1/7/2009 8:00am B.Sisko  In  
1/7/2009 8:00am K.Janeway In 
1/5/2009 8:00am K.Janeway In  
1/1/2009 8:00am J.Picard  Out  Vacation 

Tôi muốn truy vấn dữ liệu và trả lại trạng thái gần đây nhất cho mỗi người dùng, trong trường hợp này, truy vấn của tôi sẽ trả về các kết quả sau:

Date    User   Status Notes 
------------------------------------------------------- 
1/8/2009 12:00pm B.Sisko  In  Out to lunch  
1/7/2009 8:00am K.Janeway In 
1/1/2009 8:00am J.Picard  Out  Vacation 

Tôi đang cố gắng tìm ra câu lệnh TRANSACT-SQL để thực hiện điều này? Bất kỳ trợ giúp sẽ được đánh giá cao.

+2

Hahaha ... timesheet Starfleet. –

Trả lời

63

Tổng hợp trong bảng yêu cầu subquery có nguồn gốc và sau đó tham gia.

Select Date, User, Status, Notes 
    from [SOMETABLE] 
    inner join 
    (
     Select max(Date) as LatestDate, [User] 
     from [SOMETABLE] 
     Group by User 
    ) SubMax 
    on [SOMETABLE].Date = SubMax.LatestDate 
    and [SOMETABLE].User = SubMax.User 
+4

Đây được gọi là bảng dẫn xuất. – SurroundedByFish

+0

Hoạt động hoàn hảo :-) – Fox

+5

Hãy cẩn thận nếu bảng dẫn xuất kết thúc với các bản sao cho {LatestDate, User} – alphadogg

41

cách khác, điều này sẽ quét bảng chỉ một lần thay vì hai lần nếu bạn sử dụng một subquery

chỉ sql server 2005 và lên

select Date, User, Status, Notes 
from (
     select m.*, row_number() over (partition by user order by Date desc) as rn 
     from [SOMETABLE] m 
    ) m2 
where m2.rn = 1; 
+0

Magic, tôi đã có thể giải quyết truy vấn phức tạp liên quan đến việc tham gia 3 bảng và chỉ chọn mục nhập mới nhất cho từng loại dựa trên mã này . Cảm ơn bạn! – Sopuli

+1

Điều này có cùng chi phí trong kế hoạch thực hiện như câu trả lời được chấp nhận nhưng khi bạn cần nhóm theo nhiều cột ví dụ như orgID, Month, Year, câu trả lời này là sạch hơn về mặt ngữ nghĩa. – gooddadmike

+0

điều này sẽ chọn ngẫu nhiên bản ghi trong tất cả các bản ghi bằng đầu tiên theo thứ tự. –

7

Bảng có nguồn gốc sẽ làm việc, nhưng nếu đây là SQL 2005, CTE và ROW_NUMBER có thể sạch hơn:

WITH UserStatus (User, Date, Status, Notes, Ord) 
as 
(
SELECT Date, User, Status, Notes, 
    ROW_NUMBER() OVER (PARTITION BY User ORDER BY Date DESC) 
FROM [SOMETABLE] 
) 

SELECT User, Date, Status, Notes from UserStatus where Ord = 1 

Điều này cũng sẽ tạo điều kiện thuận lợi cho việc xóa chơi các trạng thái x gần đây nhất từ ​​mỗi người dùng.

4

Một cách dễ dàng:

SELECT Date, User, Status, Notes 
FROM Test_Most_Recent 
WHERE Date in (SELECT MAX(Date) from Test_Most_Recent group by User) 
+3

Liệu truy vấn này có sai không nếu hai người dùng cập nhật trạng thái của họ cùng một lúc, nhưng thời gian đó không phải là hoạt động mới nhất cho một trong số họ? – SooDesuNe

+0

Mahesh, bạn cần phải cập nhật câu trả lời của bạn có tính đến nhận xét của @ SooDesuNe. –

+0

Không sử dụng SELECTS trong mệnh đề WHERE nếu bạn có thể trợ giúp. Trừ khi đó là một điều bạn cần tìm kiếm. Nếu điều này xảy ra trong một proc được lưu trữ, nó sẽ làm tăng đáng kể thời gian trả về kết quả. Đặc biệt là trên bàn lớn. –

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