PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

So berechnen Sie die Aufbewahrung Monat für Monat mit SQL

Angesichts der folgenden Testtabelle (die Sie bereitgestellt haben sollten):

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

Tabelle auth_user ist für das Problem nicht relevant.
Using tstamp als Spaltenname, da ich keine Basistypen als Bezeichner verwende.

Ich werde die Fensterfunktion lag() Wiederholungskäufer zu identifizieren. Um es kurz zu machen, kombiniere ich Aggregat- und Fensterfunktionen in einer Abfrageebene. Denken Sie daran, dass Fensterfunktionen nach angewendet werden Aggregatfunktionen.

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;

Ergebnis:

  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

Ich habe Ihre Frage erweitert, um den Unterschied zwischen der Anzahl der Transaktionen und der Anzahl der Käufer zu ermitteln.

Das OR NULL für repeat_transaction dient zur Umwandlung von FALSE auf NULL , sodass diese Werte nicht von count() gezählt werden im nächsten Schritt.

-> SQLfiddle.