PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

Как да изчислим задържането месец спрямо месец с помощта на SQL

Предвид следната тестова таблица (която трябваше да предоставите):

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

Таблица auth_user не е от значение за проблема.
Използване на tstamp като име на колона, тъй като не използвам базови типове като идентификатори.

Ще използвам функцията за прозорец lag() за идентифициране на повтарящи се купувачи. За да бъда кратък, комбинирам агрегатни и прозоречни функции в едно ниво на заявка. Имайте предвид, че функциите на прозореца се прилагат след агрегатни функции.

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;

Резултат:

  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

Разширих въпроса ви, за да осигуря разликата между броя на транзакциите и броя на купувачите.

OR NULL за repeat_transaction служи за преобразуване на FALSE на NULL , така че тези стойности не се отчитат от count() в следващата стъпка.

-> 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. Разделете данните в колоните, разделени със запетая, на допълнителни колони

  2. PostgreSQL now() и лятно часово време

  3. Как да запазите данните да не се сортират?

  4. Автоматизирани надстройки на PostgreSQL клъстери в облак с почти нулев престой (част I)

  5. Изчислени / изчислени / виртуални / извлечени колони в PostgreSQL