64 votes

Requête SQL pour obtenir la ligne la plus récente pour chaque instance d'une clé donnée

J'essaie d'obtenir l'IP, l'utilisateur et l'horodatage le plus récent d'une table pouvant contenir à la fois l'adresse IP actuelle d'un utilisateur et un ou plusieurs ips antérieurs. Je voudrais une ligne pour chaque utilisateur contenant l'adresse IP la plus récente et l'horodatage associé. Donc si une table ressemble à ceci:

 username      |  ip      |  time_stamp  
--------------|----------|--------------  
ted           | 1.2.3.4  | 10  
jerry         | 5.6.6.7  | 12  
ted           | 8.8.8.8  | 30
 

Je m'attendrais à ce que le résultat de la requête soit:

 jerry    |  5.6.6.7   |  12
ted      |  8.8.8.8   |  30
 

Puis-je faire cela dans une seule requête SQL? Si cela compte, le SGBD est Postgresql.

94voto

Chris Nielsen Points 7492

Essaye ça:

 Select u.[username]
      ,u.[ip]
      ,q.[time_stamp]
From [users] As u
Inner Join (
    Select [username]
          ,max(time_stamp) as [time_stamp]
    From [users]
    Group By [username]) As [q]
On u.username = q.username
And u.time_stamp = q.time_stamp
 

8voto

Kim Gräsman Points 5027

Quelque chose comme ça:

 select * 
from User U1
where time_stamp = (
  select max(time_stamp) 
  from User 
  where username = U1.username)
 

devrait le faire.

3voto

user2323503 Points 28

Les deux réponses ci-dessus, supposons que vous n'avez qu'une ligne pour chaque utilisateur et time_stamp. En fonction de l'application et de la granularité de votre time_stamp cela peut ne pas être une hypothèse valable. Si vous avez besoin de traiter avec des liens de time_stamp pour un utilisateur donné, vous auriez besoin d'étendre l'une des réponses données ci-dessus.

Pour écrire cela en une seule requête, il faudrait une imbriquée des sous-requêtes - les choses vont commencer à obtenir plus salissant et les performances peuvent en souffrir.

J'aurais aimé avoir ajouté ce qu'un commentaire, mais je n'ai pas encore de 50 points de réputation, donc désolé pour les de poster une nouvelle réponse!

0voto

jawz101 Points 24

Je l'utilise parce que je renvoie les résultats d'une autre table. Bien que j'essaie d'éviter la jointure imbriquée si cela aide avec un pas de moins. Tant pis. Il retourne la même chose.

 select
users.userid
, lastIP.IP
, lastIP.maxdate

from users

inner join (
    select userid, IP, datetime
    from IPAddresses
    inner join (
        select userid, max(datetime) as maxdate
        from IPAddresses
        group by userid
        ) maxIP on IPAddresses.datetime = maxIP.maxdate and IPAddresses.userid = maxIP.userid
    ) as lastIP on users.userid = lastIP.userid
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X