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

Policz aktywnych użytkowników przy użyciu znacznika czasu logowania w MySQL

Zademonstruję taki pomysł w oparciu o to, co jest dla mnie najbardziej sensowne i sposób, w jaki odpowiedziałbym, gdyby pytanie zostało przedstawione tak samo jak tutaj:

Najpierw załóżmy, że zestaw danych jako taki, nazwiemy tabelę logins :

+---------+---------------------+
| user_id |   login_timestamp   |
+---------+---------------------+
|       1 | 2015-09-29 14:05:05 |
|       2 | 2015-09-29 14:05:08 |
|       1 | 2015-09-29 14:05:12 |
|       4 | 2015-09-22 14:05:18 |
|   ...   |          ...        |
+---------+---------------------+

Mogą istnieć inne kolumny, ale nam to nie przeszkadza.

Przede wszystkim powinniśmy określić granice tego tygodnia, w tym celu możemy użyć ADDDATE() . W połączeniu z ideą, że dzisiejsza data-dzisiejszy dzień tygodnia (metoda DAYOFWEEK() w MySQL ) to niedziela.

Na przykład:jeśli dzisiaj jest środa 10, Wed - 3 = Sun , zatem 10 - 3 = 7 i możemy spodziewać się, że niedziela będzie siódmą.

Możemy uzyskać WeekStart i WeekEnd znaczniki czasu w ten sposób:

SELECT
DATE_FORMAT(ADDDATE(CURDATE(), INTERVAL 1-DAYOFWEEK(CURDATE()) DAY), "%Y-%m-%d 00:00:00") WeekStart, 
DATE_FORMAT(ADDDATE(CURDATE(), INTERVAL 7-DAYOFWEEK(CURDATE()) DAY), "%Y-%m-%d 23:59:59") WeekEnd;

Uwaga:w PostgreSQL istnieje DATE_TRUNC() funkcja, która zwraca początek określonej jednostki czasu, podając datę, taką jak początek tygodnia, miesiąc, godzina itd. Ale to nie jest dostępne w MySQL.

Następnie wykorzystajmy WeekStart i WeekEnd w celu wyselekcjonowania naszego zestawu danych, w tym przykładzie pokażę tylko, jak filtrować, używając na stałe zakodowanych dat:

SELECT *
FROM `logins`
WHERE login_timestamp BETWEEN '2015-09-29 14:05:07' AND '2015-09-29 14:05:13'

Powinno to zwrócić nasz zestaw danych w postaci wycinków z tylko istotnymi wynikami:

+---------+---------------------+
| user_id |   login_timestamp   |
+---------+---------------------+
|       2 | 2015-09-29 14:05:08 |
|       1 | 2015-09-29 14:05:12 |
+---------+---------------------+

Możemy wtedy zredukować nasz zestaw wyników tylko do user_id si odfiltrować duplikaty. następnie policz w ten sposób:

SELECT COUNT(DISTINCT user_id)
FROM `logins`
WHERE login_timestamp BETWEEN '2015-09-29 14:05:07' AND '2015-09-29 14:05:13'

DISTINCT odfiltruje duplikaty, a licznik zwróci tylko kwotę.

W połączeniu otrzymujemy:

SELECT COUNT(DISTINCT user_id)
FROM `logins`
WHERE login_timestamp 
    BETWEEN DATE_FORMAT(ADDDATE(CURDATE(), INTERVAL 1- DAYOFWEEK(CURDATE()) DAY), "%Y-%m-%d 00:00:00") 
        AND DATE_FORMAT(ADDDATE(CURDATE(), INTERVAL 7- DAYOFWEEK(CURDATE()) DAY), "%Y-%m-%d 23:59:59")

Zastąp CURDATE() z dowolnym znacznikiem czasu, aby uzyskać liczbę zalogowanych użytkowników w tym tygodniu.

Ale muszę to rozłożyć na kilka dni, słyszę jak płaczesz. Oczywiście! a oto jak:

Najpierw przetłumaczmy nasze nadmiernie informacyjne znaczniki czasu na same dane daty. Dodajemy DISTINCT ponieważ nie przeszkadza nam, że ten sam użytkownik loguje się dwa razy tego samego dnia. liczymy użytkowników, a nie loginy, prawda? (zauważ, że cofamy się tutaj):

SELECT DISTINCT user_id, DATE_FORMAT(login_timestamp, "%Y-%m-%d")
FROM `logins`

To daje:

+---------+-----------------+
| user_id | login_timestamp |
+---------+-----------------+
|       1 | 2015-09-29      |
|       2 | 2015-09-29      |
|       4 | 2015-09-22      |
|   ...   |        ...      |
+---------+-----------------+

To zapytanie zawiniemy w sekundę, aby policzyć pojawienie się każdej daty:

SELECT `login_timestamp`, count(*) AS 'count'
FROM (SELECT DISTINCT user_id, DATE_FORMAT(login_timestamp, "%Y-%m-%d") AS `login_timestamp` FROM `logins`) `loginsMod`
GROUP BY `login_timestamp`

Używamy licznika i grupowania, aby uzyskać listę według daty, która zwraca:

+-----------------+-------+
| login_timestamp | count |
+-----------------+-------+
| 2015-09-29      | 1     +
| 2015-09-22      | 2     +
+-----------------+-------+

A po całej ciężkiej pracy obie połączone:

SELECT `login_timestamp`, COUNT(*)
FROM (
SELECT DISTINCT user_id, DATE_FORMAT(login_timestamp, "%Y-%m-%d") AS `login_timestamp`
FROM `logins`
WHERE login_timestamp BETWEEN DATE_FORMAT(ADDDATE(CURDATE(), INTERVAL 1- DAYOFWEEK(CURDATE()) DAY), "%Y-%m-%d 00:00:00") AND DATE_FORMAT(ADDDATE(CURDATE(), INTERVAL 7- DAYOFWEEK(CURDATE()) DAY), "%Y-%m-%d 23:59:59")) `loginsMod`
GROUP BY `login_timestamp`;

Daje ci dzienny podział logowań na dzień w tym tygodniu. Ponownie zastąp CURDATE() aby uzyskać inny tydzień.

Jeśli chodzi o samych użytkowników, którzy się zalogowali, połączmy te same rzeczy w innej kolejności:

SELECT `user_id`
FROM (
    SELECT `user_id`, COUNT(*) AS `login_count`
    FROM (
        SELECT DISTINCT `user_id`, DATE_FORMAT(`login_timestamp`, "%Y-%m-%d")
        FROM `logins`) `logins`
    GROUP BY `user_id`) `logincounts`
WHERE `login_count` > 6

Mam dwa wewnętrzne zapytania, pierwsze to logins :

SELECT DISTINCT `user_id`, DATE_FORMAT(`login_timestamp`, "%Y-%m-%d")
FROM `logins`

Dostarczy listę użytkowników i dni, w których się logowali, bez duplikatów.

Następnie mamy logincounts :

SELECT `user_id`, COUNT(*) AS `login_count`
FROM `logins` -- See previous subquery.
GROUP BY `user_id`) `logincounts`

Zwróci tę samą listę z liczbą logowań każdego użytkownika.

I na koniec:WYBIERZ user_id Z logincounts -- Zobacz poprzednie podzapytanie.GDZIE login_count> 6

Filtrowanie tych, którzy nie zalogowali się 7 razy, i upuszczanie kolumny daty.

Trochę to trwało długo, ale myślę, że jest pełne pomysłów i myślę, że na pewno może pomóc w ciekawym udzieleniu odpowiedzi podczas rozmowy kwalifikacyjnej. :)



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. MySqlDb rzuca Operand powinien zawierać 1 kolumnę (kolumny) w instrukcji insert ignore

  2. Ekskluzywna transakcja Laravel 4 z aktualizacją i wyborem

  3. Przekaż tablicę PHP przez jQuery Ajax

  4. Jak zmienić numerację kolumny w doktrynie

  5. SQL:Wybieranie liczby wielu tabel