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 précédents. 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 le faire dans une seule requête SQL? Si cela compte, le SGBD est Postgresql.
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
Belle solution élégante avec la fonction de fenêtre ROW_NUMBER (supporté par PostgreSQL - voir dans SQL Fiddle):
SELECT username, ip, time_stamp FROM (
SELECT username, ip, time_stamp,
ROW_NUMBER() OVER (PARTITION BY username ORDER BY time_stamp DESC) rn
FROM Users
) tmp WHERE rn = 1;
Quelque chose comme ça:
select *
from User U1
where time_stamp = (
select max(time_stamp)
from User
where username = U1.username)
devrait le faire.
Les deux réponses ci-dessus supposent que vous n'avez qu'une seule ligne pour chaque utilisateur et time_stamp. Selon l’application et la granularité de votre horodatage, cette hypothèse peut ne pas être valide. Si vous avez besoin de traiter les liens de time_stamp pour un utilisateur donné, vous devez approfondir l’une des réponses données ci-dessus.
L'écrire dans une requête nécessiterait une autre sous-requête imbriquée - les choses commenceraient à devenir plus compliquées et les performances pourraient en souffrir.
J'aurais bien aimé ajouter ceci en tant que commentaire, mais je n'ai pas encore 50 ans, je suis désolé de vous avoir envoyé une nouvelle réponse!
Vous ne pouvez pas encore publier de commentaires, mais la réponse de @Cristi S est un régal pour moi.
Dans mon scénario, je devais conserver uniquement les 3 enregistrements les plus récents dans Lowest_Offers pour tous les product_ids.
Nécessité de retravailler son code SQL pour le supprimer - pensait que cela irait, mais la syntaxe est fausse.
DELETE from (
SELECT product_id, id, date_checked,
ROW_NUMBER() OVER (PARTITION BY product_id ORDER BY date_checked DESC) rn
FROM lowest_offers
) tmp WHERE > 3;
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