sql >> Databáze >  >> RDS >> PostgreSQL

Jak vypočítat retenci měsíc po měsíci pomocí SQL

Vzhledem k následující testovací tabulce (kterou byste měli poskytnout):

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

Tabulka auth_user není pro problém relevantní.
Pomocí tstamp jako název sloupce, protože nepoužívám základní typy jako identifikátory.

Budu používat funkci okna lag() k identifikaci opakovaných kupujících. Aby to bylo krátké, kombinuji agregační a okenní funkce v jedné úrovni dotazu. Mějte na paměti, že funkce okna se použijí po agregační funkce.

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;

Výsledek:

  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

Rozšířil jsem vaši otázku o rozdíl mezi počtem transakcí a počtem kupujících.

OR NULL pro repeat_transaction slouží ke konverzi FALSE na NULL , takže tyto hodnoty se nepočítají pomocí count() v dalším kroku.

-> SQLfiddle.



  1. Jak zjistit zablokování v Mysql / innodb?

  2. Oracle 11g - nejefektivnější způsob vkládání více řádků

  3. Pole PHP mysql načte každý záznam

  4. SQL Vytváření závislostí tabulek