Mysql
 sql >> Base de données >  >> RDS >> Mysql

Compter les utilisateurs actifs en utilisant l'horodatage de connexion dans MySQL

Je vais démontrer une telle idée en me basant sur ce qui me semble le plus logique et sur la façon dont je répondrais si la question était présentée comme ici :

Tout d'abord, supposons un ensemble de données en tant que tel, nous nommerons la table 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 |
|   ...   |          ...        |
+---------+---------------------+

Il peut y avoir d'autres colonnes, mais cela ne nous dérange pas.

Tout d'abord, nous devons déterminer les frontières de cette semaine, pour cela nous pouvons utiliser ADDDATE() . Combiné avec l'idée que la date d'aujourd'hui est le jour de la semaine d'aujourd'hui (DAYOFWEEK() de MySQL ), est la date du dimanche.

Par exemple :Si aujourd'hui est le mercredi 10, Wed - 3 = Sun , donc 10 - 3 = 7 , et nous pouvons nous attendre à ce que dimanche soit le 7.

Nous pouvons obtenir WeekStart et WeekEnd horodatages de cette manière :

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;

Remarque :dans PostgreSQL, il existe un DATE_TRUNC() fonction qui renvoie le début d'une unité de temps spécifiée, à partir d'une date, telle que le début de la semaine, le mois, l'heure, etc. Mais ce n'est pas disponible dans MySQL.

Ensuite, utilisons WeekStart et weekEnd afin de cliquer sur notre ensemble de données, dans cet exemple, je vais juste montrer comment filtrer, en utilisant des dates codées en dur :

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

Cela devrait renvoyer notre ensemble de données découpé en tranches, avec uniquement des résultats pertinents :

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

Nous pouvons alors réduire notre jeu de résultats au seul user_id s, et filtrez les doublons. puis comptez, de cette façon :

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 filtrera les doublons et count renverra uniquement le montant.

Combiné, cela devient :

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

Remplacer CURDATE() avec n'importe quel horodatage afin d'obtenir le nombre de connexions d'utilisateurs de cette semaine.

Mais j'ai besoin de décomposer ça en jours, je t'entends pleurer. Bien sûr! et voici comment :

Tout d'abord, traduisons nos horodatages trop informatifs en données de date uniquement. Nous ajoutons DISTINCT car cela ne nous dérange pas que le même utilisateur se connecte deux fois le même jour. nous comptons les utilisateurs, pas les connexions, n'est-ce pas ? (notez que nous revenons ici):

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

Cela donne :

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

Cette requête, nous la terminerons par une seconde, afin de compter les apparitions de chaque date :

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`

Nous utilisons count et un regroupement afin d'obtenir la liste par date, qui renvoie :

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

Et après tout le travail acharné, les deux combinés :

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

Vous donnera une répartition quotidienne des connexions par jour au cours de cette semaine. Encore une fois, remplacez CURDATE() pour obtenir une autre semaine.

Quant aux utilisateurs eux-mêmes qui se sont connectés, combinons les mêmes éléments dans un ordre différent :

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

J'ai deux requêtes internes, la première est logins :

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

Fournit la liste des utilisateurs et les jours où ils se sont connectés, sans doublons.

Ensuite, nous avons logincounts :

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

Renverra la même liste, avec un décompte du nombre de connexions de chaque utilisateur.

Et enfin :SELECT user_id FROM logincounts -- Voir la sous-requête précédente.WHERE login_count> 6

Filtrage de ceux qui ne se sont pas connectés 7 fois et suppression de la colonne de date.

C'est un peu long, mais je pense que c'est plein d'idées et je pense que cela peut certainement aider à répondre de manière intéressante lors d'un entretien de travail. :)