Query esploratore dati per tutti gli utenti attivi (Lurker + Poster)

Sto cercando di fornire al nostro team statistiche sul numero di utenti attivi attuali, con la seguente definizione di “Utente Attivo”:

Utenti che hanno letto mentre erano connessi oppure hanno pubblicato sul nostro forum nell’ultimo anno

Abbiamo molti utenti in modalità “Lista di distribuzione” che rispondono via email, quindi ne perderemmo molti se raccogliessimo semplicemente il numero di lettori come in questa query:

Posso anche ottenere il numero di chi ha pubblicato qui:

Sono solo troppo limitato per combinarli con un OR in modo da includere entrambi i gruppi. Puoi aiutarmi?

Questo dovrebbe restituirti tutti gli utenti che hanno letto qualcosa mentre erano connessi o che hanno pubblicato nell’ultimo anno. L’esploratore di dati mostrerà anche il numero totale di tali utenti.

SELECT p.user_id
FROM posts p
LEFT JOIN topics t ON t.id = p.topic_id
WHERE p.created_at::date > CURRENT_TIMESTAMP - INTERVAL '365 days'
 AND t.deleted_at IS NULL
 AND t.visible = TRUE
 AND t.closed = FALSE
 AND t.archived = FALSE
 AND t.archetype = 'regular'
 AND p.deleted_at IS NULL
UNION
SELECT u.user_id
FROM user_visits u
WHERE u.posts_read > 0
 AND u.visited_at > CURRENT_TIMESTAMP - INTERVAL '365 days'
ORDER BY user_id

Probabilmente esiste un modo più efficiente per farlo, ma questo funziona :slight_smile: . Se desideri un periodo specifico, puoi sostituire > CURRENT_TIMESTAMP - INTERVAL '365 days' (in entrambi i casi) con qualcosa del genere: BETWEEN '20200101'::date AND '20210101'::date.

Hai fornito ottime informazioni e riferimenti nella tua domanda! Ho dovuto solo selezionare gli elementi giusti e combinarli.

Grazie! Credo fermamente nel rendere il più facile possibile per gli altri dare una mano, quando possibile.

UNION – quella era la lacuna nelle mie conoscenze SQL. Tutto risolto, grazie! Pubblicherò qui la mia query finale una volta che sarà più raffinata.

Alla fine ho optato per qualcosa di leggermente diverso, poiché volevo più informazioni e UNION si è rivelato un po’ restrittivo. Volevo anche suddividere i dati per gruppi. Ho raggiunto il successo (credo) modificando la query inclusa per gli utenti attivi con un’altra query che ho per estrarre informazioni specifiche del gruppo:

-- [params]
-- int :number_of_days = 365
-- string :group_name = trust_level_0

With included_users AS (
SELECT
gu.user_id
FROM group_users gu
JOIN groups g
ON g.id = gu.group_id
WHERE g.name = :group_name
),
posts_by_user AS (
    SELECT COUNT(*) AS posts, p.user_id
    FROM posts p
    LEFT JOIN topics t ON t.id = p.topic_id
    WHERE p.created_at::date > CURRENT_TIMESTAMP - INTERVAL ':number_of_days' day
        AND t.deleted_at IS NULL
        AND t.visible = TRUE
        AND t.closed = FALSE
        AND t.archived = FALSE
        AND t.archetype = 'regular'
        AND p.deleted_at IS NULL
    GROUP BY p.user_id
), 
posts_read_by_user AS (
    SELECT SUM(posts_read) AS posts_read, uv.user_id
    FROM user_visits uv
    WHERE uv.posts_read > 0
        AND uv.visited_at > CURRENT_TIMESTAMP - INTERVAL ':number_of_days' day
    GROUP BY uv.user_id
)

SELECT
    u.id AS "user_id",
    u.username_lower AS "username",
    u.last_seen_at,
    COALESCE(pbu.posts, 0) AS "posts_created",
    COALESCE(prbu.posts_read, 0) AS "posts_read"
FROM users u
LEFT JOIN posts_by_user pbu ON pbu.user_id = u.id
LEFT JOIN posts_read_by_user prbu ON prbu.user_id = u.id
WHERE u.active = true
    AND u.id > 0
    AND u.id IN (SELECT user_id FROM included_users)
    AND (COALESCE(pbu.posts, 0) > 0 OR COALESCE(prbu.posts_read, 0) > 0)
ORDER BY u.id

Grazie per aver condiviso questo. Ho provato a usarlo e anche un codice molto simile sulle query di badge, ma ottengo questo errore:

Violazione del contratto:
La query non restituisce una colonna 'granted_at'

Mi manca qualcosa nel codice per poter usare questa query sul sistema di badge? Il mio caso d’uso è automatizzare il gruppo dei ‘lurker’ :slight_smile:

Astuto!

Le query per i badge sono piuttosto complicate e richiedono solo ‘user_id’ e ‘granted_at’ per essere restituite. Quindi dovrai fare un po’ di hacking.

Ti consiglio di approfondire gli argomenti relativi alle query per i badge (leggili attentamente) e di fare un tentativo. Ti consiglio anche di eseguirla solo una volta al giorno, altrimenti potrebbe essere un po’ pesante.

Facci sapere come procede!