Расширенный SQL с оконной функцией - PullRequest
0 голосов
/ 06 марта 2020

У меня есть Таблица a (Таблица измерений) и Таблица B (Таблица фактов), где хранится история покупок транзакций.

Таблица a: идентификатор покупки (суррогатный ключ), созданный для уникальной комбинации (любой из столбца 2, столбец3, в столбце 4 повторяется, у него будет тот же идентификатор покупателя)

Таблица b - данные транзакции. enter image description here

Я пытаюсь идентифицировать новых клиентов и постоянных клиентов для каждой недели, ожидаемый результат ниже.

enter image description here

Я думаю следующее SQL Заявление

Выберите COUNT (*) OVER (PARTITION BY shopperid, weekdate) в качестве total_new_shopperid для повторного клиента, для идентификации нового клиента (ie уникального) в том же условие соединения, я застрял на оконной функции ..

спасибо,

Сэм

Ответы [ 2 ]

1 голос
/ 06 марта 2020

Вы можете использовать аналитическую функцию DENSE_RANK вместе с агрегатной функцией следующим образом:

SELECT WEEK_DATE, 
       COUNT(DISTINCT CASE WHEN DR = 1 THEN SHOPPER_ID END) AS TOTAL_NEW_CUSTOMER,
       SUM(CASE WHEN DR = 1 THEN AMOUNT END) AS TOTAL_NEW_CUSTOMER_AMT,
       COUNT(DISTINCT CASE WHEN DR > 1 THEN SHOPPER_ID END) AS TOTAL_REPEATED_CUSTOMER,
       SUM(CASE WHEN DR > 1 THEN AMOUNT END) AS TOTAL_REPEATED_CUSTOMER_AMT 
  FROM
      (
        select T.*, 
               DENSE_RANK() OVER (PARTITION BY SHOPPER_ID ORDER BY WEEK_DATE) AS DR
          FROM YOUR_TABLE T);
GROUP BY WEEK_DATE;

Cheers !!

0 голосов
/ 06 марта 2020

Теджа sh в порядке ответа (и я его голосую).

Однако Oracle довольно эффективен при агрегировании, поэтому два уровня агрегации могут иметь лучшую производительность (в зависимости от данные):

select week_date,
       sum(case when min_week_date = week_date then 1 else 0 end) as new_shoppers,
       sum(case when min_week_date = week_date then amount else 0 end) as new_shopper_amount,
       sum(case when min_week_date > week_date then 1 else 0 end) as returning_shoppers,
       sum(case when min_week_date > week_date then amount else 0 end) as returning_amount
from (select shopper_id, week_date,
             sum(amount) as amount,
             min(week_date) over (partition by shopper_id) as min_week_date
      from t
      group by shopper_id, week_date
     ) sw
group by week_date
order by week_date;

Примечание: если это имеет лучшую производительность, это, вероятно, из-за исключения count(distinct).

...