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

Comment calculer la rétention mois après mois en utilisant SQL

Étant donné le tableau de test suivant (que vous auriez dû fournir) :

CREATE TEMP TABLE transaction (buyer_id int, tstamp timestamp);
INSERT INTO transaction VALUES 
 (1,'2012-01-03 20:00')
,(1,'2012-01-05 20:00')
,(1,'2012-01-07 20:00')  -- multiple transactions this month
,(1,'2012-02-03 20:00')  -- next month
,(1,'2012-03-05 20:00')  -- next month
,(2,'2012-01-07 20:00')
,(2,'2012-03-07 20:00')  -- not next month
,(3,'2012-01-07 20:00')  -- just once
,(4,'2012-02-07 20:00'); -- just once

Tableau auth_user n'est pas pertinent pour le problème.
Utilisation de tstamp comme nom de colonne car je n'utilise pas les types de base comme identifiants.

Je vais utiliser la fonction de fenêtre lag() pour identifier les acheteurs récurrents. Pour faire court, je combine les fonctions d'agrégation et de fenêtre dans un même niveau de requête. Gardez à l'esprit que les fonctions de fenêtre sont appliquées après fonctions d'agrégation.

WITH t AS (
   SELECT buyer_id
         ,date_trunc('month', tstamp) AS month
         ,count(*) AS item_transactions
         ,lag(date_trunc('month', tstamp)) OVER (PARTITION BY  buyer_id
                                           ORDER BY date_trunc('month', tstamp)) 
          = date_trunc('month', tstamp) - interval '1 month'
            OR NULL AS repeat_transaction
   FROM   transaction
   WHERE  tstamp >= '2012-01-01'::date
   AND    tstamp <  '2012-05-01'::date -- time range of interest.
   GROUP  BY 1, 2
   )
SELECT month
      ,sum(item_transactions) AS num_trans
      ,count(*) AS num_buyers
      ,count(repeat_transaction) AS repeat_buyers
      ,round(
          CASE WHEN sum(item_transactions) > 0
             THEN count(repeat_transaction) / sum(item_transactions) * 100
             ELSE 0
          END, 2) AS buyer_retention
FROM   t
GROUP  BY 1
ORDER  BY 1;

Résultat :

  month  | num_trans | num_buyers | repeat_buyers | buyer_retention_pct
---------+-----------+------------+---------------+--------------------
 2012-01 |         5 |          3 |             0 |               0.00
 2012-02 |         2 |          2 |             1 |              50.00
 2012-03 |         2 |          2 |             1 |              50.00

J'ai étendu votre question pour fournir la différence entre le nombre de transactions et le nombre d'acheteurs.

Le OR NULL pour repeat_transaction sert à convertir FALSE à NULL , donc ces valeurs ne sont pas comptées par count() à l'étape suivante.

-> SQLfiddle.