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

È possibile con MySQL?

Un altro aggiornamento: Accidentalmente (tramite copia e incolla) aveva starttime = ... or starttime = ... ma dovrebbe essere starttime = ... or endtime = ...

AGGIORNAMENTO:

Per spiegare la mia domanda in modo più dettagliato (nella query finale ci sono ancora più commenti):

Per prima cosa abbiamo semplicemente

SELECT
...
FROM gc_sessions s
WHERE DATE(starttime) = CURDATE() OR DATE(endtime) = CURDATE()

Non è più come dire "dammi tutti gli utenti la cui sessione è iniziata oggi o è terminata oggi". Il dover considerare queste due volte ancora e ancora rende la query un po' goffa, ma in realtà non è così complicata.

Quindi, di solito useremmo la funzione COUNT() per contare qualcosa, ovviamente, ma poiché vogliamo il "conteggio condizionale", usiamo semplicemente la funzione SUM() e le diciamo quando aggiungere 1 e quando no.

SUM (CASE WHEN ... THEN 1 ELSE 0 END) AS a_column_name

La funzione SUM() esamina ora ogni riga nel set di risultati delle sessioni di oggi. Quindi, per ogni utente in questo set di risultati, controlliamo se questo utente era online la data specificata. Non importa quante volte è stato online, quindi per motivi di prestazioni utilizziamo EXISTS . Con EXISTS puoi specificare una sottoquery che si interrompe non appena viene trovato qualcosa, quindi non importa cosa restituisce quando viene trovato qualcosa, purché non sia NULL . Quindi non confonderti perché ho selezionato 1 . Nella subquery dobbiamo connettere l'utente che è attualmente esaminato dalla query esterna con l'utente dalla query interna (subquery) e specificare la finestra temporale. Se tutti i criteri soddisfano, conta 1 altro 0 come spiegato prima.

SUM(CASE WHEN 
         EXISTS (SELECT 1 FROM gc_sessions sub_s WHERE s.user = sub_s.user 
                  AND ((date(starttime) = CURDATE() - INTERVAL 1 DAY) 
                       OR (date(endtime) = CURDATE() - INTERVAL 1 DAY))) 
    THEN 1 ELSE 0 END) AS todayAndYesterday,

Quindi creiamo una colonna per ogni condizione e voilà, hai tutto ciò di cui hai bisogno in una query. Quindi, con la tua domanda aggiornata, i tuoi criteri sono cambiati, dobbiamo solo aggiungere altre regole:

SELECT
/*this is like before*/
SUM(CASE WHEN 
         EXISTS (SELECT 1 FROM gc_sessions sub_s WHERE s.user = sub_s.user 
                  AND ((date(starttime) = CURDATE() - INTERVAL 1 DAY) 
                       OR (date(endtime) = CURDATE() - INTERVAL 1 DAY))) 
    THEN 1 ELSE 0 END) AS FridayAndThursday,
SUM(CASE WHEN 
         EXISTS (SELECT 1 FROM gc_sessions sub_s WHERE s.user = sub_s.user 
                  AND ((date(starttime) = CURDATE() - INTERVAL 2 DAY) 
                       OR (date(endtime) = CURDATE() - INTERVAL 2 DAY)))
         /*this one here is a new addition, since you don't want to count the users that were online yesterday*/
         AND NOT EXISTS (SELECT 1 FROM gc_sessions sub_s WHERE s.user = sub_s.user 
                  AND ((date(starttime) = CURDATE() - INTERVAL 1 DAY) 
                       OR (date(endtime) = CURDATE() - INTERVAL 1 DAY)))
    THEN 1 ELSE 0 END) AS FridayAndWednesdayButNotThursday,
SUM(CASE WHEN 
         EXISTS (SELECT 1 FROM gc_sessions sub_s WHERE s.user = sub_s.user 
                  AND ((date(starttime) = CURDATE() - INTERVAL 3 DAY) /* minus 3 days to get tuesday*/
                       OR (date(endtime) = CURDATE() - INTERVAL 3 DAY)))
         /*this is the same as before, we check again that the user was not online between today and tuesday, but this time we really use BETWEEN for convenience*/
         AND NOT EXISTS (SELECT 1 FROM gc_sessions sub_s WHERE s.user = sub_s.user 
                  AND ((date(starttime) BETWEEN CURDATE() - INTERVAL 2 DAY AND CURDATE() - INTERVAL 1 DAY) 
                       OR (date(endtime) BETWEEN CURDATE() - INTERVAL 2 DAY AND CURDATE() - INTERVAL 1 DAY)))
    THEN 1 ELSE 0 END) AS FridayAndTuesdayButNotThursdayAndNotWednesday,
.../*and so on*/
FROM gc_sessions s
WHERE DATE(starttime) = CURDATE() OR DATE(endtime) = CURDATE()

Quindi, spero che tu abbia l'idea ora. Altre domande? Sentiti libero di chiedere.

fine aggiornamento

Risposta alla versione precedente della domanda:

select 
SUM(CASE WHEN EXISTS (SELECT 1 FROM gc_sessions sub_s WHERE s.user = sub_s.user 
                      AND ((date(starttime) = CURDATE() - INTERVAL 1 DAY) 
                           OR (date(starttime) = CURDATE() - INTERVAL 1 DAY))) 
    THEN 1 ELSE 0 END) AS todayAndYesterday,
SUM(CASE WHEN EXISTS (SELECT 1 FROM gc_sessions sub_s WHERE s.user = sub_s.user 
                      AND ((date(starttime) BETWEEN CURDATE() - INTERVAL 2 DAY AND CURDATE() - INTERVAL 1 DAY) 
                           OR (date(starttime) BETWEEN CURDATE() - INTERVAL 2 DAY AND CURDATE() - INTERVAL 1 DAY))) 
    THEN 1 ELSE 0 END) AS todayAndYesterdayOrTheDayBeforeYesterday,
SUM(CASE WHEN EXISTS (SELECT 1 FROM gc_sessions sub_s WHERE s.user = sub_s.user 
                      AND ((date(starttime) BETWEEN CURDATE() - INTERVAL 7 DAY AND CURDATE() - INTERVAL 1 DAY) 
                           OR (date(starttime) BETWEEN CURDATE() - INTERVAL 7 DAY AND CURDATE() - INTERVAL 1 DAY))) 
    THEN 1 ELSE 0 END) AS todayAndWithinTheLastWeek
from gc_sessions s
where date(starttime) = CURDATE()
or date(endtime) = CURDATE()