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

Er dette muligt med mysql?

En anden opdatering: Ved et uheld (ved copy&paste) havde starttime = ... or starttime = ... men det skal være starttime = ... or endtime = ...

OPDATERING:

For at forklare min forespørgsel mere detaljeret (i den sidste forespørgsel er der endnu flere kommentarer):

Først fik vi bare

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

Det er ikke mere som at sige "giv mig alle brugere, hvis session startede i dag eller sluttede i dag". At skulle overveje disse to gange igen og igen gør forespørgslen lidt klodset, men faktisk er det ikke så kompliceret.

Så normalt ville vi bruge COUNT()-funktionen til at tælle noget, selvfølgelig, men da vi ønsker "betinget tælling", bruger vi simpelthen SUM()-funktionen og fortæller den, hvornår den skal tilføje 1 og hvornår ikke.

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

Funktionen SUM() undersøger nu hver række i resultatsættet af sessioner fra i dag. Så for hver bruger i dette resultatsæt ser vi, om denne bruger var online den dato, vi angiver. Det er ligegyldigt, hvor mange gange han/hun var online, så af præstationsmæssige årsager bruger vi EXISTS . Med EXISTS du kan angive en underforespørgsel, der stopper, så snart noget er fundet, så det er lige meget, hvad det returnerer, når noget er fundet, så længe det ikke er NULL . Så bliv ikke forvirret, hvorfor jeg valgte 1 . I underforespørgslen skal vi forbinde den bruger, som i øjeblikket undersøges fra den ydre forespørgsel, med brugeren fra den indre forespørgsel (underforespørgsel) og angive tidsvinduet. Hvis alle kriterier opfylder tæller 1 ellers 0 som forklaret før.

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,

Så laver vi en kolonne for hver betingelse og voila, du har alt hvad du behøver i én forespørgsel. Så med dit opdaterede spørgsmål er dine kriterier ændret, vi skal bare tilføje flere regler:

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

Så jeg håber du får ideen nu. Har du flere spørgsmål? Spørg endelig.

slut på opdatering

Svar på tidligere version af spørgsmålet:

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


  1. SQL Server SP - Pass parameter for IN array liste?

  2. opdatere forespørgsel med join på to tabeller

  3. Sådan afinstalleres postgresql på min Mac (kører Snow Leopard)

  4. Migrering af en Oracle-database fra AWS EC2 til AWS RDS, del 4