webentwicklung-frage-antwort-db.com.de

Wie frage ich SQL nach dem neuesten Aufnahmedatum für jeden Benutzer ab?

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.

180
fishhead
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
311
RedFilter

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
90
dotjoe

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;
37
sujeet

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
)
19
Alison R.
SELECT *     
FROM MyTable T1    
WHERE date = (
   SELECT max(date)
   FROM MyTable T2
   WHERE T1.username=T2.username
)
7
Manix

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
2
Peter Lang

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).

EXISTIERT NICHT

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

ZEILENNUMMER

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

INNER JOIN

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

LINKE ÄUSSERE VERBINDUNG

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'".

2
Fabian Pijcke

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
1
imba22

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.

0
Dheeraj Kumar

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
0
user2014518

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
0
Mahmoud Hawa
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
0
David
SELECT *
FROM ReportStatus c
inner join ( SELECT 
  MAX(Date) AS MaxDate
  FROM ReportStatus ) m
on  c.date = m.maxdate
0
Narmadha
SELECT * FROM TABEL1 WHERE DATE= (SELECT MAX(CREATED_DATE) FROM TABEL1)
0
AJAY
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.

0
Philip Kelley

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
0
James Moore

Meine kleine Zusammenstellung

  • selbst join besser als verschachtelt select
  • aber group by gibt Ihnen nicht primary key, was für join vorzuziehen ist
  • dieser Schlüssel kann durch partition 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:

  • Filtern Sie Daten mit der Anweisung where in einer beliebigen Spalte
  • select Spalten aus gefilterten Zeilen

Nachteile:

  • Benötige MS SQL Server ab 2012.
0
resnyanskiy

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));    
0
Sajee