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

Utilisateurs actifs hebdomadaires pour chaque jour du journal

Pour obtenir un nombre "d'utilisateurs moyens hebdomadaires" (selon ma compréhension de vos spécifications... "pour chaque jour, le nombre d'identifiants d'utilisateurs distincts vus ce jour-là et les six jours précédents"), une requête similaire à celle ci-dessous peut être utilisé. (La requête renvoie également le nombre "Daily Average User".

SELECT d.day
     , COUNT(DISTINCT u.user_id) AS wau
     , COUNT(DISTINCT IF(u.day=d.day,u.user_id,NULL)) AS dau
  FROM ( SELECT FLOOR(k.ts/86400) AS `day`
           FROM `log` k
          GROUP BY `day`
       ) d
  JOIN ( SELECT FLOOR(l.ts/86400) AS `day`
              , l.user_id
           FROM `log` l
          GROUP BY `day`, l.user_id
       ) u
    ON u.day <= d.day
   AND u.day > d.day - 7
 GROUP BY d.day
 ORDER BY d.day

(Je n'ai pas encore testé cela, mais je le ferai plus tard, et je mettrai à jour cette déclaration si des corrections sont nécessaires.)

Cette requête rejoint la liste des utilisateurs pour un jour donné (depuis le u rowsource), à ​​un ensemble de jours de la table de journal (le d source de ligne). Notez le "7" littéral qui apparaît dans le prédicat de jointure (la clause ON), c'est ce qui fait que la liste d'utilisateurs "correspond" aux 6 jours précédents.

Notez que cela pourrait également être étendu pour obtenir le nombre d'utilisateurs distincts au cours des 3 derniers jours, par exemple, en ajoutant une autre expression dans la liste SELECT.

     , COUNT(DISTINCT IF(u.day<=d.day AND u.day>d.day-3,u.user_id,NULL)) AS 3day

Ce "7" littéral pourrait être augmenté pour obtenir une plage plus large. Et ce littéral 3 dans l'expression ci-dessus pourrait être changé pour obtenir n'importe quel nombre de jours... nous devons juste être sûrs que nous avons suffisamment de lignes du jour précédent (de d ) joint à chaque ligne à partir de u .

REMARQUE SUR LES PERFORMANCES :en raison des vues en ligne (ou des tables dérivées, comme MySQL les appelle), cette requête peut ne pas être très rapide, car les résultats de ces vues en ligne doivent être matérialisés dans des tables MyISAM intermédiaires.

La vue en ligne alias u peut ne pas être optimal ; il peut être plus rapide de se joindre directement à la table de journal. Je pensais en termes d'obtention d'une liste unique d'utilisateurs pour un jour donné, ce que cette requête dans la vue en ligne m'a apporté. C'était juste plus facile pour moi de conceptualiser ce qui se passait. Et je pensais que si vous aviez des centaines du même utilisateur entré pour le jour, la vue en ligne éliminerait tout un tas de doublons, avant que nous fassions la jointure aux autres jours. Une clause WHERE pour limiter le nombre de jours que nous sont de retour seraient mieux ajoutés à l'intérieur du u et d vues en ligne. (Le d la vue intégrée devrait inclure un délai supplémentaire de 6 jours.)

Sur une autre note, si la colonne ts est le type de données TIMESTAMP, je serais plus enclin à utiliser un DATE(ts) expression pour extraire la partie date. Mais cela renverrait un type de données DATE dans le jeu de résultats, plutôt qu'un entier, qui serait différent du jeu de résultats que vous avez spécifié.)

SELECT d.day
     , COUNT(DISTINCT u.user_id) AS wau
     , COUNT(DISTINCT IF(u.day=d.day,u.user_id,NULL)) AS dau
  FROM ( SELECT DATE(k.ts) AS `day`
           FROM `log` k
          GROUP BY `day`
       ) d
  JOIN ( SELECT DATE(l.ts) AS `day`
              , l.user_id
           FROM `log` l
          GROUP BY `day`, l.user_id
       ) u
    ON u.day <= d.day
   AND u.day > DATE_ADD(d.day, INTERVAL -7 DAY)
 GROUP BY d.day
 ORDER BY d.day