2010-07-07 26 views
5

J'ai une requête simple et je me demande si elle pourrait être plus élégamment codée. La solution finale doit être compatible ansi.Instruction SQL pour sélectionner la valeur de la dernière version de données basée sur la dernière date

J'ai besoin d'extraire la dernière valeur d'une table en fonction de la date et de la version. Un échantillon expliquerait plus clairement:

declare @t table (id int, due_date smalldatetime, version int, value nvarchar(10)) 

insert into @t select 3, '1/1/2010', 1, 'value 1' 
insert into @t select 3, '1/1/2010', 2, 'value 2' 
insert into @t select 3, '3/1/2010', 1, 'value 3' 
insert into @t select 3, '3/1/2010', 2, 'value 4' 
insert into @t select 3, '3/1/2010', 3, 'value 5' 
insert into @t select 3, '3/1/2010', 4, 'value 6' 
insert into @t select 3, '4/1/2010', 1, 'value 7' 
insert into @t select 3, '4/1/2010', 2, 'value 8' 
insert into @t select 3, '4/1/2010', 3, 'value 9' 


select value from @t t 
    inner join (select due_date, version=max(version) 
       from @t where due_date = (select max(due_date) from @t) group by due_date) maxes 
    on t.due_date=maxes.due_date and t.version=maxes.version 

donc j'attendre que la sortie soit

value 9 

qui elle est basée sur la requête ci-dessus.

Je ne suis pas particulièrement satisfait de cette solution - de meilleurs moyens pour y parvenir?

Répondre

5

Vous pouvez utiliser:

SELECT TOP 1 
     x.value 
    FROM @t x 
ORDER BY x.due_date DESC, x.version DESC 

TOP n'est pas ANSI, cependant. Une autre option serait d'utiliser des fonctions analytiques ANSI/Classement/fenêtrage:

SELECT x.value 
    FROM (SELECT t.value, 
       ROW_NUMBER() OVER (ORDER BY t.due_date DESC, t.version DESC) AS rank 
      FROM @t t) x 
WHERE x.rank = 1 

Mais cela nécessite une base de données qui prend en charge la fonctionnalité - MySQL n'a pas, PostgreSQL n'a commencé à v8.4 ...

+0

Haha, c'est si simple qu'elle n'a même pas traversé l'esprit ... ce – cjk

+0

était incroyablement rapide (les réponses, c'est). Je n'ai jamais vraiment utilisé les fonctions de classement - je pense qu'il est grand temps d'apprendre ... Merci pour les réponses. EDIT: il s'agit de SQL Server 2005 – Sean

+0

@Sean: Je recommande d'utiliser TOP avant ROW_NUMBER pour cet exemple, ou d'envisager l'une des requêtes de Tom H. –

1
SELECT 
    value 
FROM 
    @t T1 
LEFT OUTER JOIN @t T2 ON 
    T2.id = T1.id AND 
    (
     (T2.due_date > T1.due_date) OR 
     (T2.due_date = T1.due_date AND T2.version > T1.version) 
    ) 
WHERE 
    T2.id IS NULL 

ou ...

SELECT 
    value 
FROM 
    @t T1 
WHERE 
    NOT EXISTS 
    (
     SELECT 
     FROM 
      @t T2 
     WHERE 
      T2.id = T1.id AND 
      (
       (T2.due_date > T1.due_date) OR 
       (T2.due_date = T1.due_date AND T2.version > T1.version) 
      ) 
    )