web-dev-qa-db-fra.com

Requête SQL pour renvoyer un seul enregistrement par ID de groupe

Je cherche un moyen de gérer le scénario suivant. J'ai une table de base de données sur laquelle je dois renvoyer un seul enregistrement pour chaque "identifiant de groupe" contenu dans la table. En outre, l'enregistrement sélectionné dans chaque groupe doit être la personne la plus âgée du ménage.

ID   Group ID   Name               Age
1   134        John Bowers        37
2   134        Kerri Bowers       33
3   135        John Bowers        44
4   135        Shannon Bowers     42

Ainsi, dans les exemples de données fournis ci-dessus, les ID 1 et 3 doivent être renvoyés, car ce sont les personnes les plus âgées de chaque ID de groupe.

Ceci est interrogé sur une base de données SQL Server 2005.

19
Richard West
SELECT  t.*
FROM    (
        SELECT  DISTINCT groupid
        FROM    mytable
        ) mo
CROSS APPLY
        (
        SELECT  TOP 1 *
        FROM    mytable mi
        WHERE   mi.groupid = mo.groupid
        ORDER BY
                age DESC
        ) t

ou ca:

SELECT  *
FROM    (
        SELECT  *, ROW_NUMBER() OVER (PARTITION BY groupid ORDER BY age DESC) rn
        FROM    mytable
        )
WHERE   rn = 1

Cela renverra au plus un enregistrement par groupe, même en cas d'égalité.

Voir cet article sur mon blog pour comparer les performances des deux méthodes:

29
Quassnoi

Utilisation:

SELECT DISTINCT
       t.groupid,
       t.name
  FROM TABLE t
  JOIN (SELECT t.groupid,
               MAX(t.age) 'max_age'
          FROM TABLE t
      GROUP BY t.groupid) x ON x.groupid = t.groupid
                           AND x.max_age = t.age

Alors que se passe-t-il s'il y a 2 personnes ou plus du même âge dans un groupe? Il serait préférable de stocker la date de naissance plutôt que l'âge - vous pouvez toujours calculer la date de naissance pour la présentation.

3
OMG Ponies
SELECT GroupID, Name, Age
FROM table
INNER JOIN
(
SELECT GroupID, MAX(Age) AS OLDEST
FROM table
) AS OLDESTPEOPLE
ON
table.GroupID = OLDESTPEOPLE.GroupID
AND
table.Age = OLDESTPEOPLE.OLDEST
0
Chris Simmons

Essayez ceci (en supposant que Groupe est synonyme de Ménage )

Select * From Table t
Where Age = (Select Max(Age)
             From Table 
             Where GroupId = t.GroupId)

S'il y a au moins deux personnes "plus âgées" dans un ménage (elles ont toutes le même âge et il n'y a personne d'autre), alors elles seront toutes renvoyées, pas seulement une au hasard.

S'il s'agit d'un problème, vous devez ajouter une autre sous-requête pour renvoyer une valeur de clé arbitraire pour une personne de cet ensemble.

Select * From Table t
Where Id = 
  (Select Max(Id) Fom Table 
   Where GroupId = t.GroupId
      And Age =
         (Select(Max(Age) From Table
          Where GroupId = t.GroupId))
0
Charles Bretana