sql >> Base de Datos >  >> RDS >> Mysql

¿Es esto posible con mysql?

Otra actualización: Accidentalmente (por copiar y pegar) tenía starttime = ... or starttime = ... pero debería ser starttime = ... or endtime = ...

ACTUALIZACIÓN:

Para explicar mi consulta con más detalle (en la consulta final hay aún más comentarios):

Primero simplemente obtuvimos

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

Eso no es más como decir "dame todos los usuarios cuya sesión comenzó hoy o finalizó hoy". Tener que considerar esas dos veces una y otra vez hace que la consulta sea un poco torpe, pero en realidad no es tan complicado.

Por lo tanto, normalmente usaríamos la función COUNT() para contar algo, obviamente, pero como queremos un "conteo condicional", simplemente usamos la función SUM() y le decimos cuándo agregar 1 y cuándo no.

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

La función SUM() examina ahora cada fila en el conjunto de resultados de las sesiones de hoy. Entonces, para cada usuario en este conjunto de resultados, buscamos si este usuario estuvo en línea en la fecha que especificamos. No importa cuántas veces estuvo en línea, así que por razones de rendimiento usamos EXISTS . Con EXISTS puede especificar una subconsulta que se detenga tan pronto como se encuentre algo, por lo que no importa lo que devuelva cuando se encuentre algo, siempre que no sea NULL . Así que no te confundas por qué seleccioné 1 . En la subconsulta, tenemos que conectar el usuario que se examina actualmente desde la consulta externa con el usuario de la consulta interna (subconsulta) y especificar la ventana de tiempo. Si todos los criterios cumplen, cuente 1, de lo contrario 0, como se explicó antes.

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,

Luego creamos una columna para cada condición y listo, tiene todo lo que necesita en una consulta. Entonces, con su pregunta actualizada, su criterio ha cambiado, solo tenemos que agregar más reglas:

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

Entonces, espero que ahora entiendas la idea. ¿Alguna pregunta más? Siéntete libre de preguntar.

fin de la actualización

Respuesta a la versión anterior de la pregunta:

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