Ich habe eine Tabelle, die Auflistungseinträge darüber enthält, wann ein Benutzer angemeldet war.
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..
Wie erstelle ich eine Abfrage, mit der ich für jeden Benutzer das neueste Datum erhalte?
pdate: Ich habe vergessen, dass ich einen Wert haben muss, der zum letzten Datum passt.
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
Verwenden von Fensterfunktionen (funktioniert in 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
Ich sehe, dass die meisten Entwickler eine Inline-Abfrage verwenden, ohne die Auswirkungen auf große Datenmengen zu berücksichtigen.
Einfach gesagt, können Sie dies erreichen, indem Sie:
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;
So rufen Sie die gesamte Zeile ab, die das maximale Datum für den Benutzer enthält:
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
)
Dieser sollte Ihnen das richtige Ergebnis für Ihre bearbeitete Frage liefern.
Die Unterabfrage stellt sicher, dass nur Zeilen mit dem neuesten Datum gefunden werden, und das äußere GROUP BY
Kümmert sich um Bindungen. Wenn für denselben Benutzer zwei Einträge für dasselbe Datum vorhanden sind, wird der Eintrag mit dem höchsten value
zurückgegeben.
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
Nach meiner Erfahrung ist der schnellste Weg, jede Zeile zu nehmen, für die es keine neuere Zeile in der Tabelle gibt. Hier ist ein kleiner Benchmark mit einigen Daten, die ich zur Hand habe.
Ein weiterer Vorteil ist, dass die verwendete Syntax sehr einfach ist und die Bedeutung der Abfrage ziemlich leicht zu verstehen ist (nehmen Sie alle Zeilen so, dass für den zu berücksichtigenden Benutzernamen keine neueren Zeilen vorhanden sind).
SELECT username, value
FROM t
WHERE NOT EXISTS (
SELECT *
FROM t AS witness
WHERE witness.date > t.date
);
Erläutern Sie die Gesamtkosten: 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
Gesamtkosten: 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;
Erläutern Sie die Gesamtkosten: 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
Erläutern Sie die Gesamtkosten: 62.964
Die EXPLAIN-Pläne stammen aus einer Datenbank mit etwa 10.000 Zeilen, die als XML gespeichert sind. Die verwendeten Abfragen enthalten auch ein Prädikat "group_id = '1'".
Sie können auch die analytische Rangfunktion verwenden
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)
Die innere Abfrage gibt das letzte Datum für den aktuellen Benutzer zurück. Die äußere Abfrage zieht alle Daten entsprechend dem Ergebnis der inneren Abfrage.
Oracle sortiert die Ergebnismenge in absteigender Reihenfolge und nimmt den ersten Datensatz auf, sodass Sie den neuesten Datensatz erhalten:
select * from mytable
where rownum = 1
order by date desc
Auf diese Weise habe ich den letzten Datensatz für jeden Benutzer erstellt, den ich auf meinem Tisch habe. Es war eine Abfrage, um den letzten Standort für den Verkäufer zu ermitteln, der zuletzt auf PDA Geräten festgestellt wurde.
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
Würde das aktualisierte Problem beheben. Bei großen Tabellen funktioniert dies möglicherweise nicht so gut, selbst bei guter Indizierung.
Dies ähnelt einer der obigen Antworten, ist aber meiner Meinung nach viel einfacher und aufgeräumter. Zeigt auch eine gute Verwendung für die Cross Apply-Anweisung. Für SQL Server 2005 und höher ...
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
Meine kleine Zusammenstellung
join
besser als verschachtelt select
group by
gibt Ihnen nicht primary key
, was für join
vorzuziehen istpartition by
in Verbindung mit first_value
( docs ) vergeben werden.Also, hier ist eine Abfrage:
Wählen Sie t. * aus Tabelle ) als ID aus Tabelle wobei FilterColumn = 'value' ) j auf t.ID = j.ID
Vorteile:
where
in einer beliebigen Spalteselect
Spalten aus gefilterten ZeilenNachteile:
Ich habe für meine Bewerbung etwas gemacht als es:
Unten ist die Abfrage:
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));