2009-06-02 11 views
5

Ho una domanda che fa un numero di join e ha alcuni criteri nella clausola WHERE, e sto finendo con un risultato che appare essenzialmente come questo:gruppo SQL problema

| userId |  date | otherData | 
|--------+------------+------------| 
|  1 | 2008-01-01 | different | 
|  1 | 2009-01-01 |  info | 
|  1 | 2010-01-01 |  for | 
|  2 | 2008-01-01 |  each | 
|  3 | 2008-01-01 |  row | 
|  3 | 2009-01-01 |  here | 

Così , in sostanza per ogni utente, ci saranno una o più date nel passato e 0 o più date in futuro.

Devo in qualche modo ridurre il set di dati a una riga per utente, selezionando solo la riga che ha la data passata più recente. Vale a dire, con tutto ciò che la magia GROUP BY o HAVING clausola è aggiunto, il risultato dall'alto sarebbe simile a questa:

| userId |  date | otherData | 
|--------+------------+------------| 
|  1 | 2009-01-01 |  info | 
|  2 | 2008-01-01 |  each | 
|  3 | 2009-01-01 |  here | 

risposta

5

penso che non si desidera utilizzare GROUP BY/AVENDO perché siete interessati a esattamente 1 fila per utente, e quella riga esiste già nella tabella così com'è. Ciò richiede una clausola WHERE e non GROUP BY/HAVING.

Il mio suggerimento è che nella clausola WHERE, si aggiunge una condizione che la data deve essere uguale al risultato di una sottoquery. Che subquery dovrebbe:

  1. Selezionare il massimo (data)
  2. una clausola WHERE che limita data ad essere più piccoli di adesso
  3. Avere una clausola WHERE con UserID uguale di query esterna user id

Per evitare casi in cui un determinato utente può avere due voci con la stessa data che è anche la data massima "passata", è necessario aggiungere anche DISTINCT.

Spero che questo aiuti.

+0

funziona bene !! ma aggiungendo DISTINCT non rimuovendo valori duplicati, nessun suggerimento? – Rakesh

0

Ti piace questa:

select a.userId, a.date, b.userId, b.otherData 
from table1 as a 
left outer join table2 as b on a.userId = b.userId 
where b.Id in (
    select top 1 Id from table2 as c where c.userId = a.userId) 
0
 
Select 
    userID, date, otherData 
from 
    yourTable t1 
where 
    date = 
    (select max(date) from yourTable t2 
    where t1.userID=t2.userID) 
0
select T.userid, T.date, T.otherdata 
from 
    T, 
    (select userid, max(date) max_date from T group by userid) GT 
where 
    T.userid = GT.userid and T.date = GT.max_date 

Spiegazione: interno selezionare - izolate solo i record con la data massima per ogni utente. intera selezione - unire record izolati con la tabella originale, per ottenere il campo otherdata.

Supponevo che ci fosse una sola data massima per un id utente. Si prega di dire se è l'assunzione corretta.