Activité de visite de groupe

Activité de visite de groupe

Je travaille sur des requêtes qui analysent l’activité des groupes.

  • Visiteurs uniques
  • Nombre total de visites
  • Visites mobiles par rapport aux visites sur ordinateur de bureau
  • Pourcentage d’adhérents du groupe ayant effectué une visite
  • Temps de lecture moyen par visite
  • Nombre moyen de publications lues par visite
  • Temps de lecture moyen par adhérent
  • Nombre moyen de publications lues par adhérent

Questions

  1. Je soupçonne que la table user_visits ne capture qu’un seul enregistrement par user_id unique par jour, étant donné que visited_at est de type DATE et non DATETIME ou TIMESTAMP, même si l’utilisateur effectue plusieurs visites dans la journée à partir de différents types d’appareils. Lorsque j’exécute ma requête par JOUR, je constate que le nombre total d’adhérents uniques est égal au nombre total de visites. Quelqu’un peut-il confirmer si mon hypothèse est correcte ? Si c’est le cas, la question suivante devient : que devient la valeur pour mobile si l’utilisateur effectue trois visites dans la journée, d’abord depuis un ordinateur portable, puis un ordinateur de bureau, puis un téléphone, dans n’importe quel ordre ?
  2. Étrangement, je constate également que AVG(uv.posts_read) n’a pas la même valeur que SUM(uv.posts_read)/COUNT(DISTINCT(uv.user_id)). Je serais donc curieux de savoir où ma requête fait fausse route ou si j’interprète incorrectement la table user_visits ou ses champs. Quelqu’un peut-il intervenir pour expliquer la différence entre ces deux calculs ?

Requête :

Résumé
-- [paramètres]
-- chaîne null :group_name = VotreNomDeGroupe
-- date :start_date = 2019/09/01
-- date :end_date = 2019/10/01
-- chaîne null :frame = day

with mobile as (
SELECT uv.id,
    count(DISTINCT(uv.user_id)) as UniqueMobile,
    date_part(:frame, uv.visited_at::date) as Day,
    g.name as GroupName
from user_visits uv
join users u on uv.user_id = u.id
join group_users gu on gu.user_id = u.id
join groups g on g.id = gu.group_id
where mobile = true
    and uv.visited_at >= :start_date::date
    and uv.visited_at < :end_date::date
    and g.name = :group_name
GROUP BY GroupName, Day, uv.id
    ), 
    
desktop as (
SELECT uv.id,
    count(DISTINCT(uv.user_id)) as UniqueDesktop,
    date_part(:frame, uv.visited_at::date) as Day,
    g.name as GroupName
from user_visits uv
join users u on uv.user_id = u.id
join group_users gu on gu.user_id = u.id
join groups g on g.id = gu.group_id
where mobile = false
    and uv.visited_at >= :start_date::date
    and uv.visited_at < :end_date::date
    and g.name = :group_name
GROUP BY GroupName, Day, uv.id
    )

   SELECT 
    date_part(:frame, uv.visited_at::date) as VisitDate,
    count(DISTINCT(uv.user_id)) as UniqueMembers, 
    count(uv.id) as AllVisits,
    count(m.UniqueMobile) as MobileVisits,
    count(d.UniqueDesktop) as DesktopVisits,
    round((count(DISTINCT(uv.user_id)) * 100.0) / groups.user_count, 2) as Percent,
    round(avg(uv.posts_read),2) as "Publications lues (moyenne par visite)",
    (interval '1' minute * ROUND((cast(AVG(uv.time_read) as decimal)/60), 2)) as "Temps de lecture (moyenne par visite)",
    (SUM(uv.posts_read)/count(DISTINCT(uv.user_id))) as "Publications lues (moyenne par adhérent)",
    date_trunc('second',(interval '1' minute * (ROUND((cast(SUM(uv.time_read) as decimal)/60), 2)/(count(DISTINCT(uv.user_id)))))) as "Temps de lecture (moyenne par adhérent)"

FROM users
join group_users on group_users.user_id = users.id
join groups on group_users.group_id = groups.id
LEFT join user_visits uv on uv.user_id = users.id
LEFT JOIN mobile m ON m.id = uv.id
LEFT JOIN desktop d ON d.id = uv.id
    where groups.name = :group_name
    AND uv.visited_at::date >= :start_date
    and uv.visited_at::date < :end_date
    
group by VisitDate, groups.user_count 

order by VisitDate asc

Oui, c’est exact.

Si l’utilisateur lit des publications lors de sa visite depuis un nouvel appareil, la colonne mobile sera mise à jour en fonction du dernier appareil sur lequel il a effectué une visite. Par exemple, si un utilisateur commence sa journée en lisant 2 publications sur un navigateur de bureau, une entrée user_visits sera créée pour l’ID de l’utilisateur avec posts_read défini à 2 et mobile défini à false. Si l’utilisateur se connecte ensuite sur un appareil mobile et lit 3 publications supplémentaires, l’entrée user_visits pour la journée sera mise à jour avec posts_read: 5 et mobile: true. Vous pouvez tester cela avec l’Explorateur de données ; assurez-vous simplement que l’utilisateur lit des publications qu’il n’a pas encore lues.

Merci, avez-vous des idées sur la dernière question ? Je suis partisan de bonnes données plutôt que de mauvaises, et cela soulève des interrogations de voir des résultats similaires mais pas identiques, d’autant plus que vous avez expliqué qu’il n’y a qu’une seule uv.id par uv.user_id dans user_visits pour chaque uv.visited_at.

Cela ne sera peut-être pas très utile, mais voici un extrait de mes données :

VisitDate Posts Read (avg Visit) Read (avg Member)
13 1.18 1
14 4.15 4
15 7.18 7
16 6.15 6

Lorsque vous divisez des entiers, PostgreSQL renvoie un entier. Essayez quelque chose comme SUM(posts_read)::float / COUNT(DISTINCT(user_id)) et voyez si vous trouvez toujours une différence. Vous devrez peut-être arrondir le résultat à deux décimales.