J'ai une table qui est une collection d'entrées à quand un utilisateur a été connecté.
username, date, value
--------------------------
brad, 1/2/2010, 1.1
fred, 1/3/2010, 1.0
bob, 8/4/2009, 1.5
brad, 2/2/2010, 1.2
fred, 12/2/2009, 1.3
etc..
Comment créer une requête qui me donnerait la date la plus récente pour chaque utilisateur?
Mise à jour: J'ai oublié qu'il me fallait une valeur correspondant à la date la plus récente.
select t.username, t.date, t.value
from MyTable t
inner join (
select username, max(date) as MaxDate
from MyTable
group by username
) tm on t.username = tm.username and t.date = tm.MaxDate
Utilisation des fonctions de fenêtre (fonctionne avec Oracle, Postgres 8.4, SQL Server 2005, DB2, Sybase, Firebird 3.0, MariaDB 10.3)
select * from (
select
username,
date,
value,
row_number() over(partition by username order by date desc) as rn
from
yourtable
) t
where t.rn = 1
Je constate que la plupart des développeurs utilisent une requête en ligne sans tenir compte de son impact sur des données volumineuses.
Vous pouvez y parvenir simplement en:
SELECT a.username, a.date, a.value
FROM myTable a
LEFT OUTER JOIN myTable b
ON a.username = b.username
AND a.date < b.date
WHERE b.username IS NULL
ORDER BY a.date desc;
Pour obtenir la ligne entière contenant la date maximum pour l'utilisateur:
select username, date, value
from tablename where (username, date) in (
select username, max(date) as date
from tablename
group by username
)
SELECT *
FROM MyTable T1
WHERE date = (
SELECT max(date)
FROM MyTable T2
WHERE T1.username=T2.username
)
Celui-ci devrait vous donner le résultat correct pour votre question modifiée.
La sous-requête veille à ne rechercher que les lignes de la date la plus récente, et le GROUP BY
extérieur prendra soin des liens. Quand il y a deux entrées pour la même date pour le même utilisateur, elle retournera celle avec le plus haut value
.
SELECT t.username, t.date, MAX( t.value ) value
FROM your_table t
JOIN (
SELECT username, MAX( date ) date
FROM your_table
GROUP BY username
) x ON ( x.username = t.username AND x.date = t.date )
GROUP BY t.username, t.date
D'après mon expérience, le moyen le plus rapide est de prendre chaque ligne pour laquelle il n'y a pas de nouvelle ligne dans la table. Voici un petit repère avec certaines données que j'ai sous la main.
Un autre avantage est que la syntaxe utilisée est très simple et que la signification de la requête est assez facile à comprendre (prenez toutes les lignes de sorte qu'aucune nouvelle ligne n'existe pour le nom d'utilisateur considéré).
SELECT username, value
FROM t
WHERE NOT EXISTS (
SELECT *
FROM t AS witness
WHERE witness.date > t.date
);
Expliquez le coût total: 2.38136
SELECT username, value
FROM (
SELECT username, value, row_number() OVER (PARTITION BY username ORDER BY date DESC) AS rn
FROM t
) t2
WHERE rn = 1
Coût total: 61.5823
SELECT t.username, t.value
FROM t
INNER JOIN (
SELECT username, MAX(date) AS date
FROM t
GROUP BY username
) tm ON t.username = tm.username AND t.date = tm.date;
Expliquez le coût total: 67.5439
SELECT username, value
FROM t
LEFT OUTER JOIN t AS w ON t.username = w.username AND t.date < w.date
WHERE w.username IS NULL
Expliquez le coût total: 62.964
Les plans explicités proviennent d’une base de données contenant environ 10 000 lignes, stockée au format XML. Les requêtes utilisées contiennent également un prédicat "group_id = '1'".
Vous pouvez également utiliser la fonction de classement analytique
with temp as
(
select username, date, RANK() over (partition by username order by date desc) as rnk from t
)
select username, rnk from t where rnk = 1
Select * from table1 where lastest_date=(select Max(latest_date) from table1 where user=yourUserName)
Inner Query renverra la date la plus récente pour l'utilisateur actuel, Outer query extraira toutes les données en fonction du résultat de la requête interne.
Pour Oracle, le résultat est trié par ordre décroissant et prend le premier enregistrement. Vous obtiendrez ainsi le dernier enregistrement:
select * from mytable
where rownum = 1
order by date desc
J'ai utilisé cette façon de prendre le dernier enregistrement pour chaque utilisateur que j'ai sur ma table. C'était une requête pour obtenir le dernier emplacement du vendeur selon l'heure récemment détectée sur PDA périphériques.
CREATE FUNCTION dbo.UsersLocation()
RETURNS TABLE
AS
RETURN
Select GS.UserID, MAX(GS.UTCDateTime) 'LastDate'
From USERGPS GS
where year(GS.UTCDateTime) = YEAR(GETDATE())
Group By GS.UserID
GO
select gs.UserID, sl.LastDate, gs.Latitude , gs.Longitude
from USERGPS gs
inner join USER s on gs.SalesManNo = s.SalesmanNo
inner join dbo.UsersLocation() sl on gs.UserID= sl.UserID and gs.UTCDateTime = sl.LastDate
order by LastDate desc
SELECT t1.username, t1.date, value
FROM MyTable as t1
INNER JOIN (SELECT username, MAX(date)
FROM MyTable
GROUP BY username) as t2 ON t2.username = t1.username AND t2.date = t1.date
SELECT *
FROM ReportStatus c
inner join ( SELECT
MAX(Date) AS MaxDate
FROM ReportStatus ) m
on c.date = m.maxdate
SELECT * FROM TABEL1 WHERE DATE= (SELECT MAX(CREATED_DATE) FROM TABEL1)
SELECT Username, date, value
from MyTable mt
inner join (select username, max(date) date
from MyTable
group by username) sub
on sub.username = mt.username
and sub.date = mt.date
Adresserait le problème mis à jour. Cela pourrait ne pas fonctionner aussi bien sur les grandes tables, même avec une bonne indexation.
Ceci est similaire à l'une des réponses ci-dessus, mais à mon avis, il est beaucoup plus simple et ordonné. En outre, montre une bonne utilisation de l'instruction cross apply. Pour SQL Server 2005 et supérieur ...
select
a.username,
a.date,
a.value,
from yourtable a
cross apply (select max(date) 'maxdate' from yourtable a1 where a.username=a1.username) b
where a.date=b.maxdate
Ma petite compilation
join
meilleur que imbriqué select
group by
ne vous donne pas primary key
qui est préférable pour join
partition by
conjointement avec first_value
( docs )Donc, voici une requête:
sélectionnez t. * dans table t jointure interne ( sélectionnez une première valeur distincte (ID) sur (partition par ordre GroupColumn par DateColumn desc ) comme ID du tableau où FilterColumn = 'valeur' ) j sur t.ID = j.ID
Avantages:
where
en utilisant n'importe quelle colonneselect
toutes les colonnes des lignes filtréesLes inconvénients:
J'ai fait un peu pour mon application car il:
Ci-dessous la requête:
select distinct i.userId,i.statusCheck, l.userName from internetstatus
as i inner join login as l on i.userID=l.userID
where nowtime in((select max(nowtime) from InternetStatus group by userID));