Mysql
 sql >> Baza danych >  >> RDS >> Mysql

Czy to możliwe z mysql?

Kolejna aktualizacja: Przypadkowo (przez kopiowanie i wklejanie) miał starttime = ... or starttime = ... ale powinno to być starttime = ... or endtime = ...

AKTUALIZACJA:

Aby dokładniej wyjaśnić moje zapytanie (w ostatnim pytaniu jest jeszcze więcej komentarzy):

Najpierw po prostu otrzymaliśmy

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

To nic innego jak powiedzenie „daj mi wszystkich użytkowników, których sesja rozpoczęła się dzisiaj lub dzisiaj się zakończyła”. Konieczność ponownego rozważenia tych dwóch razy sprawia, że ​​zapytanie jest trochę niezgrabne, ale w rzeczywistości nie jest to takie skomplikowane.

Tak więc zwykle używamy funkcji COUNT(), aby coś policzyć, ale ponieważ chcemy "zliczania warunkowego", po prostu używamy funkcji SUMA() i mówimy, kiedy dodać 1, a kiedy nie.

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

Funkcja SUM() sprawdza teraz każdy wiersz w zestawie wyników sesji od dzisiaj. Tak więc dla każdego użytkownika w tym zestawie wyników sprawdzamy, czy ten użytkownik był online w określonej przez nas dacie. Nie ma znaczenia, ile razy był online, więc ze względu na wydajność używamy EXISTS . Z EXISTS możesz określić podzapytanie, które zatrzymuje się, gdy tylko coś zostanie znalezione, więc nie ma znaczenia, co zwraca, gdy coś zostanie znalezione, o ile nie jest to NULL . Więc nie daj się zwieść, dlaczego wybrałem 1 . W podzapytaniu musimy połączyć użytkownika aktualnie badanego z zapytania zewnętrznego z użytkownikiem z zapytania wewnętrznego (podzapytanie) i określić okno czasowe. Jeśli wszystkie kryteria spełniają liczbę 1, jeszcze 0, jak wyjaśniono wcześniej.

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,

Następnie tworzymy kolumnę dla każdego warunku i voila, masz wszystko, czego potrzebujesz w jednym zapytaniu. Tak więc wraz z Twoim zaktualizowanym pytaniem zmieniły się Twoje kryteria, musimy tylko dodać więcej reguł:

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

Więc mam nadzieję, że teraz wpadniesz na ten pomysł. Jakieś pytania? Śmiało pytaj.

koniec aktualizacji

Odpowiedź na poprzednią wersję pytania:

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. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Jboss mysql - Nie znaleziono odpowiedniego sterownika dla jdbc

  2. Jak zaimplementować wydajniejszą funkcję wyszukiwania?

  3. Jak mogę przeszukiwać tabelę w tabeli?

  4. Zaktualizuj datę w bazie danych o +1 miesiąc

  5. Jak zdobyć wszystkie rekordy bez usuwania w grupie w mysql