come faccio a interrogare sql per una data record più recente per ogni utente

Ho una tabella che è una raccolta di voci su quando un utente è stato registrato.

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

Come posso creare una query che mi dia la data più recente per ciascun utente?

Aggiornamento: ho dimenticato che avevo bisogno di avere un valore che va con la data più recente.

 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 

Utilizzo delle funzioni di finestra (funziona 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 

Vedo che la maggior parte degli sviluppatori usa una query inline senza considerare il suo impatto su enormi dati.

Semplicemente, puoi ottenere ciò:

 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; 

Per ottenere l’intera riga contenente la data massima per l’utente:

 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 ) 

Questo dovrebbe darti il ​​risultato corretto per la tua domanda modificata.

La sottoquery assicura di trovare solo le righe della data più recente e il GROUP BY esterno GROUP BY si occuperà dei vincoli. Quando ci sono due voci per la stessa data per lo stesso utente, restituirà quella con il value più 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 

Per Oracle ordina il risultato impostato in ordine decrescente e prende il primo record, in modo da ottenere l’ultimo record:

 select * from mytable where rownum = 1 order by date desc 
 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 

Indirizzerebbe il problema aggiornato. Potrebbe non funzionare così bene su tavoli di grandi dimensioni, anche con una buona indicizzazione.

 SELECT * FROM ReportStatus c inner join ( SELECT MAX(Date) AS MaxDate FROM ReportStatus ) m on c.date = m.maxdate 
 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 table1 where lastest_date=(select Max(latest_date) from table1 where user=yourUserName)

Inner Query restituirà la data più recente per l’utente corrente, Query esterna trarrà tutti i dati in base al risultato della query interna.

Ho usato in questo modo per prendere l’ultimo record per ogni utente che ho sul mio tavolo. Si trattava di una query per ottenere l’ultima posizione per il venditore in base all’ora recente rilevata sui dispositivi PDA.

 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 

La mia piccola compilation

  • auto join meglio di select annidato
  • ma group by non ti dà primary key che è preferibile per join
  • questa chiave può essere data per partition by in congiunzione con first_value ( docs )

Quindi, ecco una domanda:

 selezionare
  t. *
 a partire dal 
  Tabella t join interno (
   selezionare distinto first_value (ID) over (partizione di GroupColumn order by DateColumn desc) come ID
   dalla tabella
   dove FilterColumn = 'valore'
  ) j su t.ID = j.ID

Professionisti:

  • Filtra i dati con l’istruzione where usando qualsiasi colonna
  • select qualsiasi colonna da righe filtrate

Contro:

  • Ho bisogno di MS SQL Server a partire dal 2012.

Ho fatto un po ‘per la mia applicazione in quanto:

Di seguito è la query:

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

Dalla mia esperienza, il modo più veloce è quello di prendere ogni riga per la quale non ci sono nuove righe nella tabella. Ecco un piccolo punto di riferimento con alcuni dati che ho a portata di mano.

Un altro vantaggio è che la syntax utilizzata è molto semplice e che il significato della query è piuttosto semplice da comprendere (prendi tutte le righe in modo che non esistano righe più nuove per il nome utente preso in considerazione).

NON ESISTE

 SELECT username, value FROM t WHERE NOT EXISTS ( SELECT * FROM t AS witness WHERE witness.date > t.date ); 

Spiega il costo totale: 2,38136

ROW_NUMBER

 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 

Costo totale: 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; 

Spiega il costo totale: 67,5439

SINISTRA ESTERNO

 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 

Spiega il costo totale: 62.964


I piani di spiegazione provengono da un database con circa 10.000 righe, memorizzato come XML. Le query utilizzate contengono anche un predicato "group_id = '1'".

Questo è simile a una delle risposte sopra, ma secondo me è molto più semplice e ordinato. Inoltre, mostra un buon uso per la dichiarazione di cross application. Per SQL Server 2005 e versioni successive …

 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 

Dovresti utilizzare la funzione di aggregazione MAX e GROUP BY

 SELECT username, MAX(date), value FROM tablename GROUP BY username, value 
 SELECT DISTINCT Username, Dates,value FROM TableName WHERE Dates IN (SELECT MAX(Dates) FROM TableName GROUP BY Username) Username Dates value bob 2010-02-02 1.2 brad 2010-01-02 1.1 fred 2010-01-03 1.0 

Questo dovrebbe funzionare anche al fine di ottenere tutte le ultime voci per gli utenti.

 SELECT username, MAX(date) as Date, value FROM MyTable GROUP BY username, value