sql >> Database teknologi >  >> RDS >> PostgreSQL

Sådan beregner du fastholdelse måned over måned ved hjælp af SQL

Givet følgende testtabel (som du skulle have leveret):

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

Tabel auth_user er ikke relevant for problemet.
Brug af tstamp som kolonnenavn, da jeg ikke bruger basistyper som identifikatorer.

Jeg vil bruge vinduesfunktionen lag() at identificere gentagne købere. For at holde det kort kombinerer jeg aggregat- og vinduesfunktioner i ét forespørgselsniveau. Husk, at vinduesfunktioner anvendes efter aggregerede funktioner.

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;

Resultat:

  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

Jeg udvidede dit spørgsmål til at tage højde for forskellen mellem antallet af transaktioner og antallet af købere.

ELLER NULL for repeat_transaction tjener til at konvertere FALSK til NULL , så disse værdier bliver ikke talt af count() i næste trin.

-> SQLfiddle.



  1. Ydeevneimplikationer af MySQL Event Scheduling

  2. Overvågning af sidelevetid i SQL Server

  3. kan jeg bruge aggregeringsfunktionen (LAST) i mysql?

  4. Hvorfor får jeg ikke en fejl ved at indstille større INT-datatypelængde i MySQL?