2009-04-09 8 views
6

J'ai hérité d'une table avec une structure quelque chose comme ceci:Sélectionnez La plupart des États récents de l'histoire Tableau

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 est un champ d'identité et la clé primaire et il y a des indices non uniques sur le Name et Timestamp des champs.

Quel est le moyen le plus efficace pour obtenir le plus récent enregistrement pour chaque nom de l'élément, par exemple dans le tableau ci-dessus les lignes , et doivent être retournés car ils sont les plus à To- entrées de date pour les articles A, B et C respectivement.

Répondre

13

SQL Server 2005 (et suivantes):

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 exactement ce que je pensais aussi. – Sung

+0

Huh. +1 J'ai eu ceci pour fonctionner, mais je ne pourrais pas vous dire si 'MostRecentRows',' Row_Number() ', ou' PARTITION' fait la magie. – jp2code

+0

Exactement ce que je cherchais – arjun

5

En supposant qu'il n'y a pas de double horodatages par nom, quelque chose comme cela devrait fonctionner:

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 pour les sous-requêtes corrélées – Sung

+2

Oui, cela ne fonctionnerait que s'il n'y a pas d'horodatage en double. La description de l'ECU est définitivement plus sûre puisqu'elle ne retournera qu'une ligne. –

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 pour une autre solution SQL Server 2000 – Sung

+0

Cela peut renvoyer plusieurs enregistrements s'il existe plusieurs enregistrements pour un horodatage. –

+0

Je suis parfaitement conscient de ce fait. Une clause GROUP BY externe supplémentaire migre ce risque si des horodatages en double sont possibles. – Tomalak

0

Si vous utilisez SQL Server 2005/2008, la solution CTE déjà répertoriée par Mitch Weat est la meilleure de une perspective de performance. Toutefois, si vous utilisez SQL Server 2000, vous ne pouvez pas supposer qu'il n'y a pas de doublon. Combinaisons TimeStamp. Utilisez le code suivant pour retourner un seul enregistrement par nom:

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 

Donc, si vous ajoutez un autre disque comme 9 C 30, cela ne retournera ID 6. Si vous n'allez pas loin, alors vous pouvez finissent par retour 9 C 30 et C 30. 6

0

une autre façon facile:

SELECT ID,Name,Timestamp, Data 
FROM Test_Most_Recent 
WHERE Timestamp = (SELECT MAX(Timestamp) 
       FROM Test_Most_Recent 
       group by Name); 
Questions connexes