2010-09-02 6 views
0

Je table: CREATE TABLE [dbo] [Test] ( [nom] nvarchar (max) NULL, [date] NULL datetime )t-sql Aggregate Max

et les dossiers là-dessus.:

a 2010-09-02 12:00:00 
a 2010-09-02 11:00:00 
b 2010-09-02 12:00:00 
b 2010-09-02 11:00:00 

Et je veux tout nom avec la nouvelle date:

Je peut faire:

select t.[name] from test t 
group by t.[name] 
having max(date) = (select MAX(DATE) from test where [name] = t.[name]) 

qui ont un problème - je ne peux pas obtenir une date

je faire:

select t.* 
    from test t 
    where t.[date] = (select MAX(DATE) from test where [name] = t.[name]) 

qui n'a pas de problème

Ma question est: Puis-je faire mieux ?? Je vais chercher environ 10 000 enregistrements de la table incrémentale de la table (chaque jour 10 000 résultats supplémentaires).

Cordialement

Répondre

2

Quelle version de SQL Server?

SQL 2005 et plus:

SELECT * 
FROM 
    (SELECT Item = Row_Number() OVER (PARTITION BY [name] ORDER BY [date] DESC), * FROM test) X 
WHERE Item = 1 

SQL 2000:

SELECT T.* 
FROM 
    test T 
    INNER JOIN (
     SELECT [name], MaxDt = Max([date]) FROM test GROUP BY [name] 
    ) X ON T.[name] = X.[name] AND T.[date] = X.MaxDt 

Si vous pouvez avoir des dates en double puis une autre étape est nécessaire pour la version SQL Server 2000 pour le faire descendre à une ligne.

@Oded a souligné que vous pouvez simplement obtenir la date maximale. Si tout ce dont vous avez besoin est le nom et la date, alors sa requête est la meilleure. Mais si mes soupçons sont corrects et que vous avez besoin de plus d'éléments de la même rangée, vous aurez besoin de requêtes comme celles-ci.

Voici une autre version SQL 2005:

SELECT 
    T.* 
FROM 
    test T 
    CROSS APPLY (
     SELECT TOP 1 [date] 
     FROM test T2 
     WHERE T.[name] = T2.[name] 
     ORDER BY T2.[date] DESC 
    ) X 
WHERE 
    T.[date] = X.[date] 

Cette requête aura des problèmes avec les dates en double max pour le même nom

Mise à jour

Maintenant que je sais que c'est SQL 2008:

La solution row_number() est la plus simple et la plus simple. Je commencerais par ça. Si la performance ne suffit pas, et la table est un enfant d'une table parent qui a chaque [nom] une seule fois, essayez la solution CROSS Appliquer avec la table externe (test T) comme parent:

SELECT 
    X.* 
FROM 
    Parent P 
    CROSS APPLY (
     SELECT TOP 1 * 
     FROM test T 
     WHERE P.[name] = T.[name] 
     ORDER BY T.[date] DESC 
    ) X 

S'il n'y a pas de table parent, vous pouvez essayer les requêtes ci-dessus ou utilisez SELECT DISTINCT [name] FROM test mais je ne suis pas convaincu que sera une amélioration de la performance:

SELECT 
    X.* 
FROM 
    (SELECT DISTINCT [name] FROM test) P 
    CROSS APPLY (
     SELECT TOP 1 * 
     FROM test T 
     WHERE P.[name] = T.[name] 
     ORDER BY T.[date] DESC 
    ) X 
+0

J'ai utilisé sql 2008, et je veux obtenir d'autres colonnes (pas le nom et la date). Quelles solutions sont les meilleures? il peut y avoir la même date pour un seul nom – dzajdol

+0

Vous devrez juste les essayer et voir ce qui fonctionne le mieux. En outre, j'ai corrigé quelques fautes de frappe dans ma mise à jour, désolé à ce sujet. – ErikE

+0

oki thx pour les réponses – dzajdol

2

Cela permet de sélectionner des noms distincts et la date le plus récent associé à chaque:

select t.[name], MAX(t.[date]) 
from test t 
group by t.[name] 

Lorsque vous utilisez GROUP BY, vous pouvez également utiliser des fonctions d'agrégation dans la clause SELECT pour les colonnes qui ne font pas partie le groupement.

De MSDN (Aggregate Functions):

Les fonctions d'agrégation sont fréquemment utilisés avec la clause GROUP BY de l'instruction SELECT.

+0

C'est exactement ce que je vais poster. Une solution simple. – codingbadger