sql >> Databáze >  >> RDS >> Mysql

Počítejte aktivní uživatele pomocí časového razítka přihlášení v MySQL

Takovou myšlenku demonstruji na základě toho, co mi dává největší smysl, a způsobu, jakým bych odpověděl, kdyby byla otázka předložena stejně jako zde:

Nejprve předpokládejme datovou sadu jako takovou, pojmenujeme tabulku 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 |
|   ...   |          ...        |
+---------+---------------------+

Mohou existovat další sloupce, ale ty nám nevadí.

Nejprve bychom měli určit hranice tohoto týdne, k tomu můžeme použít ADDDATE() . V kombinaci s myšlenkou, že dnešní datum – dnešní den v týdnu (DAYOFWEEK() MySQL ), je nedělní datum.

Například:Pokud je dnes středa 10., Wed - 3 = Sun , tedy 10 - 3 = 7 a můžeme očekávat, že neděle bude 7.

Můžeme získat WeekStart a WeekEnd časová razítka takto:

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;

Poznámka:v PostgreSQL je DATE_TRUNC() funkce, která vrací začátek zadané časové jednotky s daným datem, jako je začátek týdne, měsíc, hodina atd. Ale to není dostupné v MySQL.

Dále použijeme WeekStart a WeekEnd k rozdělení naší datové sady, v tomto příkladu pouze ukážu, jak filtrovat pomocí pevně zakódovaných dat:

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

To by mělo vrátit naši sadu dat rozdělenou na plátky s pouze relevantními výsledky:

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

Potom můžeme snížit naši sadu výsledků pouze na user_id s a odfiltrujte duplikáty. pak počítejte takto:

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 duplikáty a count vrátí pouze částku.

Dohromady to bude:

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

Nahraďte CURDATE() s libovolným časovým razítkem, abyste získali počet přihlášení uživatele za daný týden.

Ale musím to rozdělit na dny, slyším tě plakat. Samozřejmě! a takto:

Nejprve přeložme naše příliš informativní časová razítka pouze na data. Přidáme DISTINCT protože nám nevadí, že se stejný uživatel přihlásí dvakrát ve stejný den. počítáme uživatele, ne přihlášení, že? (všimněte si, že se zde vrátíme):

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

Výsledkem je:

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

Tento dotaz zalomíme sekundou, abychom mohli počítat výskyty každého data:

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`

K získání seznamu podle data používáme počet a seskupení, které vrací:

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

A po vší dřině obojí dohromady:

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`;

Poskytne vám denní rozpis přihlášení za den v tomto týdnu. Znovu nahraďte CURDATE() získat jiný týden.

Pokud jde o samotné uživatele, kteří se přihlásili, zkombinujme stejné věci v jiném pořadí:

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

Mám dva vnitřní dotazy, první je logins :

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

Poskytne seznam uživatelů a dny, kdy se přihlásili, bez duplikátů.

Pak máme logincounts :

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

Vrátí stejný seznam s počtem přihlášení jednotlivých uživatelů.

A nakonec:SELECT user_id Z logincounts -- Viz předchozí dílčí dotaz.WHERE login_count> 6

Filtrujeme ty, kteří se 7krát nepřihlásili, a vynecháme sloupec s datem.

Bylo to trochu dlouhé, ale myslím, že je to plné nápadů a myslím, že by to určitě mohlo pomoci odpovědět zajímavým způsobem na pracovním pohovoru. :)



  1. Jak rozšířím hodnoty oddělené čárkami do samostatných řádků pomocí SQL Server 2005?

  2. Při hledání v databázi MySQL použijte znaménko '%'

  3. MySQL:Vložte více řádků se stejnou hodnotou AI

  4. Výpočet klouzavého průměru MySQL