Mysql
 sql >> Database >  >> RDS >> Mysql

Seleziona i 3 punteggi più alti in ogni giorno per ogni utente

Dai un'occhiata al codice seguente, se la tua risposta al mio commento è yes :) Dato che i tuoi dati sono tutti nel 2012 e nel mese di novembre, ho preso giorno.

Domanda:

select y.id, y.userid, y.score, y.datestamp 
from (select id, userid, score, datestamp 
      from scores
      group by day(datestamp)) as y    
where (select count(*) 
       from (select id, userid, score, datestamp
             from scores group by day(datestamp)) as x
       where y.score >= x.score
       and y.userid = x.userid
      ) =1 -- Top 3rd, 2nd, 1st    
order by y.score desc
;

Risultati:

ID  USERID  SCORE   DATESTAMP
8   2       8.5 December, 07 2012 00:00:00+0000
20  3       6   December, 08 2012 00:00:00+0000
1   1       5   December, 06 2012 00:00:00+0000

Sulla base dei tuoi ultimi aggiornamenti alla domanda. Se ne hai bisogno per utente per anno/mese/giorno e poi trovi il massimo, puoi semplicemente aggiungere una funzione di aggregazione come sum alla domanda di cui sopra. Mi sto ripetendo, dal momento che i tuoi dati di esempio sono solo per un anno, non c'è un gruppo di punti per anno o mese. Ecco perché ho preso giorno.

select y.id, y.userid, y.score, y.datestamp 
from (select id, userid, sum(score) as score,
      datestamp 
from scores
group by userid, day(datestamp)) as y    
where (select count(*) 
from (select id, userid, sum(score) as score
      , datestamp
from scores
group by userid, day(datestamp)) as x
where y.score >= x.score
and y.userid = x.userid
) =1 -- Top 3rd, 2nd, 1st    
order by y.score desc
;

Risultati basati sulla somma:

ID  USERID  SCORE   DATESTAMP
1   1       47.5    December, 06 2012 00:00:00+0000
8   2       16      December, 07 2012 00:00:00+0000
20  3       6       December, 08 2012 00:00:00+0000

AGGIORNATO CON IL NUOVO CAMPIONE DI DATI SORGENTE

Simon, per favore dai un'occhiata al mio campione. Poiché i tuoi dati stavano cambiando, ho usato i miei. Ecco il riferimento. Ho usato puro ansi style senza alcun over partition o dense_rank Nota anche che i dati che ho usato stanno ottenendo i primi 2 e non i primi 3 punteggi. Puoi cambiare di conseguenza.

Indovina un po', la risposta è 10 volte più semplice della prima impressione che hanno dato i tuoi primi dati....

SQLFIDDLE

Interroga a 1:-- per la somma dei primi 2 per utente di ogni giorno

SELECT userid, sum(Score), datestamp
FROM scores t1
where 2 >=
(SELECT count(*) 
 from scores t2
 where t1.score <= t2.score
 and t1.userid = t2.userid
 and day(t1.datestamp) = day(t2.datestamp)
 order by t2.score desc)
group by userid, datestamp 
;

Risultati per la query 1:

USERID  SUM(SCORE)  DATESTAMP
1       70      December, 06 2012 00:00:00+0000
1       30      December, 07 2012 00:00:00+0000
2       22      December, 06 2012 00:00:00+0000
2       25      December, 07 2012 00:00:00+0000
3       30      December, 06 2012 00:00:00+0000
3       30      December, 07 2012 00:00:00+0000

Query finale:-- per tutti i due giorni i primi 2 somma per utente

SELECT userid, sum(Score)
FROM scores t1
where 2 >=
(SELECT count(*) 
 from scores t2
 where t1.score <= t2.score
 and t1.userid = t2.userid
 and day(t1.datestamp) = day(t2.datestamp)
 order by t2.score desc)
group by userid
;

Risultati finali:

USERID  SUM(SCORE)
1      100
2      47
3      60

Ecco un'istantanea dei calcoli diretti dei dati che ho usato.