Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Ist das mit mysql möglich?

Noch ein Update: Versehentlich (durch Copy&Paste) hatte starttime = ... or starttime = ... aber es sollte starttime = ... or endtime = ... sein

AKTUALISIERUNG:

Um meine Abfrage genauer zu erläutern (in der letzten Abfrage gibt es noch mehr Kommentare):

Zuerst haben wir einfach

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

Das ist nichts anderes als zu sagen:"Geben Sie mir alle Benutzer, deren Sitzung heute begonnen oder heute beendet wurde". Diese beiden Male immer wieder berücksichtigen zu müssen, macht die Abfrage etwas ungeschickt, aber eigentlich ist es gar nicht so kompliziert.

Normalerweise würden wir natürlich die COUNT()-Funktion verwenden, um etwas zu zählen, aber da wir "bedingtes Zählen" wollen, verwenden wir einfach die SUM()-Funktion und sagen ihr, wann 1 addiert werden soll und wann nicht.

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

Die Funktion SUM() untersucht nun jede Zeile in der Ergebnismenge der Sitzungen von heute. Also schauen wir für jeden Benutzer in dieser Ergebnismenge, ob dieser Benutzer an dem von uns angegebenen Datum online war. Es spielt keine Rolle, wie oft er/sie online war, deshalb verwenden wir aus Leistungsgründen EXISTS . Mit EXISTS Sie können eine Unterabfrage angeben, die stoppt, sobald etwas gefunden wird, sodass es egal ist, was sie zurückgibt, wenn etwas gefunden wird, solange es nicht NULL ist . Lassen Sie sich also nicht verwirren, warum ich 1 ausgewählt habe . In der Unterabfrage müssen wir den aktuell untersuchten Benutzer aus der äußeren Abfrage mit dem Benutzer aus der inneren Abfrage (Unterabfrage) verbinden und das Zeitfenster angeben. Wenn alle Kriterien erfüllt sind, zählt 1, sonst 0, wie zuvor erklärt.

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,

Dann erstellen wir eine Spalte für jede Bedingung und voila, Sie haben alles, was Sie brauchen, in einer Abfrage. Mit Ihrer aktualisierten Frage haben sich Ihre Kriterien also geändert, wir müssen nur weitere Regeln hinzufügen:

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

So, ich hoffe, du verstehst jetzt die Idee. Noch Fragen? Fragen Sie nur.

Ende der Aktualisierung

Antwort auf die vorherige Version der Frage:

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