Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Isso é possível com o mysql?


Outra atualização: Acidentalmente (por copiar e colar) tinha starttime = ... or starttime = ... mas deve ser starttime = ... or endtime = ...

ATUALIZAÇÃO:

Para explicar minha consulta com mais detalhes (na consulta final, há ainda mais comentários):

Primeiro nós simplesmente conseguimos
SELECT
...
FROM gc_sessions s
WHERE DATE(starttime) = CURDATE() OR DATE(endtime) = CURDATE()

Isso não é nada mais do que dizer "me dê todos os usuários cuja sessão começou hoje ou terminou hoje". Ter que considerar essas duas vezes repetidamente torna a consulta um pouco desajeitada, mas na verdade não é tão complicado.

Então, normalmente usaríamos a função COUNT() para contar algo, obviamente, mas como queremos "contagem condicional", simplesmente usamos a função SUM() e informamos quando adicionar 1 e quando não.
SUM (CASE WHEN ... THEN 1 ELSE 0 END) AS a_column_name

A função SUM() examina agora cada linha no conjunto de resultados das sessões de hoje. Portanto, para cada usuário neste conjunto de resultados, verificamos se esse usuário estava online na data que especificamos. Não importa quantas vezes ele/ela esteve online, então, por motivos de desempenho, usamos EXISTS . Com EXISTS você pode especificar uma subconsulta que pare assim que algo for encontrado, então não importa o que ela retorna quando algo é encontrado, desde que não seja NULL . Portanto, não se confunda por que selecionei 1 . Na subconsulta, temos que conectar o usuário que está sendo examinado atualmente da consulta externa com o usuário da consulta interna (subconsulta) e especificar a janela de tempo. Se todos os critérios atenderem, conte 1 senão 0, como explicado anteriormente.
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,

Em seguida, criamos uma coluna para cada condição e pronto, você tem tudo o que precisa em uma consulta. Então, com sua pergunta atualizada, seus critérios mudaram, só precisamos adicionar mais regras:
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()

Então, espero que você tenha entendido agora. Mais alguma pergunta? Sinta-se a vontade para perguntar.

fim da atualização

Resposta à versão anterior da pergunta:
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()