Требуется SQL-запрос - отсчет 365 дней назад - PullRequest
0 голосов
/ 08 марта 2019

Я много раз искал форум, но не смог найти решение для своей ситуации.Я работаю с базой данных Oracle.

У меня есть таблица со всеми номерами заказов и номерами клиентов по дням.Это выглядит так:

Day | Customer Nbr | Order Nbr  
2018-01-05 | 25687459 | 256   
2018-01-09 | 36478592 | 398  
2018-03-07 | 25687459 | 1547  
and so on....

Теперь мне нужен SQL-запрос, который дает мне таблицу по дням и номер клиента и подсчитывает количество уникальных номеров заказов за последние 365 дней, начиная со столбца 1.

Для приведенного выше примера результирующая таблица должна выглядеть следующим образом:

Day | Customer Nbr | Order Cnt  
2019-01-01 | 25687459  | 2  
2019-01-02 | 25687459  | 2  
... 
2019-03-01 | 25687459  | 1  

Ответы [ 3 ]

0 голосов
/ 08 марта 2019

Один метод состоит в том, чтобы сгенерировать значения для всех интересующих дней для каждого клиента, а затем использовать коррелированный подзапрос:

with dates as (
      select date '2019-01-01' + rownum as dte from dual
      connect by date '2019-01-01' + rownum < sysdate
     )
select d.dte, t.customer_nbr,
       (select count(*)
        from t t2
        where t2.customer_nbr = t.customer_nbr and
              t2.day <= t.dte and
              t2.date > t.dte - 365
       ) as order_cnt
from dates d cross join
     (select distinct customer_nbr from t) ;
0 голосов
/ 08 марта 2019

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

Это даст вам, для каждого клиента, за каждый день количество заказов в течение одного скользящего года до отображаемой даты.

WITH DATES AS ( 
  SELECT * FROM 
    (SELECT TRUNC(SYSDATE)-(LEVEL-1) AS DAY FROM DUAL CONNECT BY TRUNC(SYSDATE)-(LEVEL-1) >= ( SELECT MIN(TRUNC(DAY)) FROM MY_TABLE )) 
    CROSS JOIN 
    (SELECT DISTINCT CUST_ID FROM MY_TABLE))
SELECT DISTINCT
    DATES.DAY,
    DATES.CUST_ID,
    COUNT(ORDER_ID) OVER (PARTITION BY DATES.CUST_ID ORDER BY DATES.DAY RANGE BETWEEN INTERVAL '1' YEAR PRECEDING AND INTERVAL '1' SECOND PRECEDING) 
FROM
  DATES
LEFT JOIN 
  MY_TABLE 
ON DATES.DAY=TRUNC(MY_TABLE.DAY) AND DATES.CUST_ID=MY_TABLE.CUST_ID
ORDER BY DATES.CUST_ID,DATES.DAY;
0 голосов
/ 08 марта 2019

Редактировать :

Я только что видел, как вы прояснили вопрос, который я интерпретировал следующим образом: для каждого дня в прошлом году показывайте, сколько заказов было накаждый клиент между этой датой и 1 годом ранее.Сейчас работаем над ответом ...

Обновленный ответ:

Для каждого клиента мы подсчитываем количество записей между днем ​​заказа и 365 днями до него ...

WITH yourTable AS
(
  SELECT SYSDATE - 1 Day, 'Alex' CustomerNbr FROM DUAL
  UNION ALL
  SELECT SYSDATE - 2, 'Alex' FROM DUAL
  UNION ALL
  SELECT SYSDATE - 366, 'Alex'FROM DUAL

  UNION ALL
  SELECT SYSDATE - 400, 'Alex'FROM DUAL
  UNION ALL
  SELECT SYSDATE - 500, 'Alex'FROM DUAL
  UNION ALL
  SELECT SYSDATE - 1, 'Joe'FROM DUAL
  UNION ALL
  SELECT SYSDATE - 300, 'Chris'FROM DUAL
  UNION ALL
  SELECT SYSDATE - 1, 'Chris'FROM DUAL
)

SELECT Day, CustomerNbr, OrdersLast365Days
FROM yourTable t
OUTER APPLY
(
  SELECT COUNT(1) OrdersLast365Days
  FROM yourTable t2
  WHERE t.CustomerNbr = t2.CustomerNbr
    AND TRUNC(t2.Day) >= TRUNC(t.Day) - 364
    AND TRUNC(t2.Day) <= TRUNC(t.Day)
)
ORDER BY t.Day DESC, t.CustomerNbr;

Last 365 Days' Orders

Если вы хотите отчитываться только за те дни, на которые у вас есть заказы, тогда достаточно простого предложения WHERE:

SELECT Day, CustomerNbr, COUNT(1) OrderCount
FROM <yourTable>
WHERE TRUNC(DAY) >= TRUNC(SYSDATE -364)
GROUP BY Day, CustomerNbr
ORDER BY Day Desc;

Если вы хотите отчитываться каждый день, сначала вам нужно сгенерировать их.Это может быть сделано с помощью рекурсивного CTE, который вы затем присоединяете к своему столу:

WITH last365Days AS
(
  SELECT TRUNC (SYSDATE - ROWNUM + 1) dt
  FROM DUAL CONNECT BY ROWNUM < 365
)

SELECT d.Day, COALESCE(t.CustomerNbr, 'None') CustomerNbr, SUM(CASE WHEN t.CustomerNbr IS NULL THEN 0 ELSE 1 END) OrderCount
FROM last365Days d
LEFT OUTER JOIN <yourTable> t
  ON d.Day = TRUNC(t.Day)
GROUP BY d.Day, t.CustomerNbr
ORDER BY d.Day Desc;

Left Join CTE

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...