2009-06-26 6 views
45

Я создаю модуль статусной платы для моей проектной команды. Плата состояния позволяет пользователю устанавливать свой статус как внутри, так и снаружи, и они также могут предоставить заметку. Я планировал на хранение всей информации в одной таблице ... и пример данных следующим образом:Создайте SQL-запрос для извлечения последних записей

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 

Я хотел бы запросить данные и возвращает последний статус для каждого пользователя, в данном случае, мой запрос будет возвращать следующие результаты:

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 

Я пытаюсь выяснить Transact-SQL, чтобы это произошло? Любая помощь будет оценена по достоинству.

+2

Хахаха ... Звездного табель. –

ответ

63

Агрегировать в подзапрос производный стол, а затем присоединиться к нему.

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

Это называется производной таблицей. – SurroundedByFish

+0

Работает отлично :-) – Fox

+5

Будьте осторожны, если производная таблица заканчивается дубликатами для {LastDate, User} – alphadogg

41

другой способ, это будет сканировать таблицу только один раз, а не два раза, если вы используете подзапрос

только SQL Server 2005 и выше

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, я смог решить сложный запрос, связанный с объединением трех таблиц и выбрав только последнюю запись для каждого типа на основе этого кода , Спасибо! – Sopuli

+1

Это соответствует той же стоимости в плане выполнения, что и принятый ответ, но когда вам нужно группировать по нескольким столбцам, например, orgID, Month, Year, этот ответ является семантически более чистым. – gooddadmike

+0

случайным образом выбирает запись из всех записей, равную первой в соответствии с заказом. –

7

Производная таблица будет работать, но если это SQL 2005, КТР и ROW_NUMBER может быть чище:

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 

Это также будет способствовать дИС воспроизведение последних статусов x от каждого пользователя.

4

Еще один простой способ:

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

Не будет ли этот запрос ошибочным, если два пользователя обновят свой статус одновременно, но это время не является последним для одного из них? – SooDesuNe

+0

Mahesh, вам необходимо обновить свой ответ с учетом комментария @ SooDesuNe. –

+0

Не используйте SELECTS в предложениях WHERE, если вы можете помочь. Если это одно время, вам нужно искать. Если это происходит в сохраненной процедуре, это значительно увеличивает время для возврата результатов. Особенно на больших столах. –

Смежные вопросы