2011-06-22 4 views
3
SELECT SomeId, ModifiedUser, MAX(ModifiedDate) 
FROM SomeTable 
GROUP BY SomeId, ModifiedUser 

Puis-je obtenir de tels résultats:groupe SQL par émission

1000 User1 Mar 30 2011 
1000 User2 Jun 25 2011 
1001 User3 Mar 21 2011 
1001 User4 Jun 20 2011 

Comment puis-je modifier la requête pour que je ne reçois que

1000 User2 Jun 25 2011 
1001 User4 Jun 20 2011 

prendre Fondamentalement, les premiers résultats de la requête puis groupe par SomeId avec les derniers ModifiedDate et ModifiedUser connectés au dernier ModifiedDate

+2

D'après votre description, votre premier résultat devrait être 'User2' et non' User1' right? –

+0

@Abe oui, désolé à ce sujet. – Connection

Répondre

3

Vous devez faire 2 requêtes et rejoindre le m.

1ère requête:

SELECT SomeId, Max(ModifiedDate) 
FROM SomeTable GROUP BY SomeId 

Ce singularise la "information unique". Ensuite, vous joignez cela avec:

SELECT SomeId, ModifiedUser, ModifiedDate 
from SomeTable 

pour vous donner toutes les données. Ainsi, la requête complète est la suivante:

SELECT SomeId, ModifiedUser, ModifiedDate 
FROM SomeTable 
INNER JOIN (
      SELECT SomeId, Max(ModifiedDate) maxmod 
      FROM SomeTable 
      GROUP BY SomeId) uniqueinfo ON SomeTable.SomeId = uniqueinfo.SomeId 
             AND ModifiedDate = uniqueinfo.maxmod 
+2

Vous devrez qualifier 'SomeId' dans cette clause SELECT, telle qu'elle existe dans les deux tables. Sinon, bonne réponse. –

1

Il existe plusieurs façons de procéder. En voici un:

SELECT 
    T1.some_id, 
    T1.modified_user, 
    T1.modified_date 
FROM 
    Some_Table T1 
INNER JOIN (
     SELECT some_id, MAX(modified_date) AS max_modified_date 
     FROM Some_Table 
     GROUP BY some_id) SQ ON 
    SQ.some_id = T1.some_id AND 
    SQ.max_modified_date = T1.modified_date 

Voici une autre:

SELECT 
    T1.some_id, 
    T1.modified_user, 
    T1.modified_date 
FROM 
    Some_Table T1 
WHERE 
    T1.modified_date = (
        SELECT MAX(T2.modified_date) 
        FROM Some_Table T2 
        WHERE T2.some_id = T1.some_id) 

Et un autre ...

SELECT 
    T1.some_id, 
    T1.modified_user, 
    T1.modified_date 
FROM 
    Some_Table T1 
LEFT OUTER JOIN Some_Table T2 ON 
    T2.some_id = T1.some_id AND 
    T2.modified_date > T1.modified_date 
WHERE 
    T2.some_id IS NULL 

La sous-requête corrélée dans la deuxième méthode a souvent des problèmes de performance, mais vous pouvez essayer tous les trois et voyez ce qui fonctionne le mieux pour vous. En outre, considérez la possibilité de "liens" dans vos dates. Si une égalité peut se produire, vous pouvez ajouter une ou plusieurs colonnes qui garantiraient l'unicité (telles que les colonnes du PK) aux première et troisième approches.

+0

+1 pour la dernière solution. Bien que, peut-être, le moins intuitif des trois, il devrait être le plus efficace. –

0

fonctions fenêtrage ont été inventées pour cela:

SELECT SomeID, ModifiedUser, ModifiedDate FROM 
(SELECT SomeID, ModifiedUser, ModifiedDate, 
    row_number() over (PARTITION BY SomeID ORDER BY ModifiedDate DESC) AS rn 
) AS subqry 
WHERE rn=1; 

Si vous voulez toutes les lignes en cas d'égalité, par rank remplacer row_number.

Vous ne mentionnez pas le choix du SGBDR. MySQL n'a pas encore cette capacité. Beaucoup d'autres le font.