Mysql
 sql >> Base de données >  >> RDS >> Mysql

Est-ce possible avec mysql ?

Une autre mise à jour : Accidentellement (par copier-coller) avait starttime = ... or starttime = ... mais ce devrait être starttime = ... or endtime = ...

MISE À JOUR :

Pour expliquer ma requête plus en détail (dans la requête finale, il y a encore plus de commentaires) :

D'abord, nous avons simplement obtenu

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

Cela revient à dire "donnez-moi tous les utilisateurs dont la session a commencé aujourd'hui ou s'est terminée aujourd'hui". Devoir considérer ces deux fois encore et encore rend la requête un peu maladroite, mais en réalité ce n'est pas si compliqué.

Donc, nous utilisons généralement la fonction COUNT() pour compter quelque chose, évidemment, mais puisque nous voulons un "comptage conditionnel", nous utilisons simplement la fonction SUM() et lui disons quand ajouter 1 et quand non.

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

La fonction SUM() examine maintenant chaque ligne dans l'ensemble de résultats des sessions à partir d'aujourd'hui. Ainsi, pour chaque utilisateur de cet ensemble de résultats, nous regardons si cet utilisateur était en ligne à la date que nous spécifions. Peu importe combien de fois il/elle était en ligne, donc pour des raisons de performances, nous utilisons EXISTS . Avec EXISTS vous pouvez spécifier une sous-requête qui s'arrête dès que quelque chose est trouvé, donc peu importe ce qu'elle renvoie quand quelque chose est trouvé, tant que ce n'est pas NULL . Alors ne vous méprenez pas sur la raison pour laquelle j'ai sélectionné 1 . Dans la sous-requête, nous devons connecter l'utilisateur qui est actuellement examiné à partir de la requête externe avec l'utilisateur de la requête interne (sous-requête) et spécifier la fenêtre de temps. Si tous les critères répondent, comptez 1 sinon 0 comme expliqué précédemment.

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,

Ensuite, nous créons une colonne pour chaque condition et le tour est joué, vous avez tout ce dont vous avez besoin en une seule requête. Donc, avec votre question mise à jour, vos critères ont changé, nous n'avons plus qu'à ajouter plus de règles :

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

Donc, j'espère que vous avez l'idée maintenant. Autres questions? N'hésitez pas à demander.

fin de la mise à jour

Réponse à la version précédente de la question :

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