2009-04-09 4 views
6

Я унаследовал таблицу с структурой что-то вроде этого:Выберите Большинство Последние Штаты Из таблицы История

ID Name Timestamp Data 
---------------------------- 
1 A  40   ... 
2 A  30   ... 
3 A  20   ... 
4 B  40   ... 
5 B  20   ... 
6 C  30   ... 
7 C  20   ... 
8 C  10   ... 

ID является поле идентификатора и первичный ключ, и есть неуникальные индексы на Name и Timestamp поля.

Что является наиболее эффективным способом, чтобы получить самую последнюю запись для каждого имени элемента, то есть в таблице выше строк , и должны быть возвращены, поскольку они самые-to даты для позиций A, B и C соответственно.

ответ

13

SQL Server 2005 (и далее):

WITH MostRecentRows AS 
(
    SELECT ID, Name, Data, 
    ROW_NUMBER() OVER (PARTITION BY Name ORDER BY TimeStamp DESC) AS 'RowNumber' 
    FROM MySchema.MyTable 
) 
SELECT * FROM MostRecentRows 
WHERE RowNumber = 1 
+0

+1 именно то, что я думал о том, как хорошо. – Sung

+0

Huh. +1. Я получил это, чтобы работать, но я не мог сказать вам, являются ли «MostRecentRows», «Row_Number()» или «PARTITION» магией. – jp2code

+0

Точно, что я искал – arjun

5

Предполагая, что нет повторяющихся отметок времени на имя, что-то, как это должно работать:

SELECT ID, Name, Timestamp, Data 
FROM test AS o 
WHERE o.Timestamp = (SELECT MAX(Timestamp) 
        FROM test as i 
        WHERE i.name = o.name) 
+0

+1 для коррелированных подзапросов – Sung

+2

Да, это будет работать, только если нет повторяющихся временных меток. Описание CTE является, безусловно, более безопасным, поскольку оно будет возвращать только одну строку. –

3

SQL Server 2000:

SELECT 
    ID, Name, Timestamp, Data 
FROM 
    DataTable 
    INNER JOIN 
    (
    SELECT ID, MAX(Timestamp) Timestamp FROM DataTable GROUP BY ID 
) latest ON 
    DataTable.ID = Latest.ID AND 
    DataTable.Timestamp = Latest.Timestamp 
+0

+1 для альтернативного решения SQL Server 2000 – Sung

+0

Это может вернуть более одной записи, если для одной метки времени есть несколько записей. –

+0

Я прекрасно это понимаю. Дополнительный внешний оператор GROUP BY переносит этот риск, если возможно дублирование временных меток. – Tomalak

0

Если вы используете SQL Server 2005/2008, то решение CTE, уже указанное Mitch Weat, является лучшим из перспектива производительности. Однако, если вы используете SQL Server 2000, вы не можете предположить, что не дублируются имя | Компоненты TimeStamp. Используйте следующий код для возврата только одна запись для каждого имени:

SELECT ID 
    , Name 
    , TimeStamp 
    , Data 
FROM DataTable dt 
INNER JOIN 
    (SELECT Name 
    , MIN(DataTable.ID) AS MinimumID 
FROM DataTable 
INNER JOIN 
    (SELECT Name 
     , MAX(Timestamp) AS Timestamp 
    FROM DataTable 
    GROUP BY Name) latest 
    ON DataTable.Name = Latest.Name 
    AND DataTable.Timestamp = Latest.Timestamp 
GROUP BY Name) MinimumLatest 
ON dt.ID = MinimumLatest.ID 

Так что, если вы добавите еще одну запись, как 9 C 30, то это будет возвращать только идентификатор 6. Если вы не ходите далеко, то вы можете в конечном итоге возвращение 9 C 30 и C 6 30.

0

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

SELECT ID,Name,Timestamp, Data 
FROM Test_Most_Recent 
WHERE Timestamp = (SELECT MAX(Timestamp) 
       FROM Test_Most_Recent 
       group by Name); 
Смежные вопросы