PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

Jak obliczyć miesiąc retencji za pomocą SQL?

Biorąc pod uwagę następującą tabelę testową (którą powinieneś był podać):

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

Tabela auth_user nie ma związku z problemem.
Korzystanie z tstamp jako nazwę kolumny, ponieważ nie używam typów bazowych jako identyfikatorów.

Użyję funkcji okna lag() do identyfikacji powtarzających się nabywców. Krótko mówiąc, łączę funkcje agregujące i okienkowe na jednym poziomie zapytania. Pamiętaj, że funkcje okna są stosowane po funkcje agregujące.

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;

Wynik:

  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

Rozszerzyłem Twoje pytanie, aby uwzględnić różnicę między liczbą transakcji a liczbą kupujących.

OR NULL dla repeat_transaction służy do konwersji FALSE na NULL , więc te wartości nie są liczone przez count() w następnym kroku.

-> SQLfiddle.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Dzień programisty PostgreSQL w Pradze 2016

  2. Ciągle otrzymuję relację błędu [TABELA] nie istnieje

  3. Micronaut nie łączy się z db w YML

  4. Jak mogę użyć zmiennej jako nazwy tabeli w node-pg?

  5. Połączenie Postgres jest wolne od PHP