Ограничение записей включенными / исключенными / нулевыми диапазонами дат - PullRequest
0 голосов
/ 08 апреля 2020

Сначала описание моей задачи. Мне нужно определить клиентов, которые разместили заказы в течение последних 2 лет. Тем не менее, мне нужно подмножество этих записей.

  1. Необходимо сделать 1 или более заказов между 12-24 месяцами go.
  2. Пробел, где НЕТ заказов размещаются в течение 1-12 месяцев, а go.
  3. 1 или более новых заказов были размещены в течение последнего месяца.

Звучит достаточно просто, но Я потратил слишком много времени на изоляцию ограничений без получения желаемого результата.

Вот моя текущая попытка кода:

SELECT * FROM
(SELECT CUSTOMER_ID AS "CUSTOMER", NAME, DATE_ENTERED,
ROW_NUMBER() OVER(PARTITION BY CUSTOMER_ID
ORDER BY DATE_ENTERED desc) SEQ
FROM
A_ATEST
WHERE
DATE_ENTERED >= ADD_MONTHS(TRUNC(sysdate),-24) AND
(DATE_ENTERED >= ADD_MONTHS(TRUNC(sysdate),-1) AND
DATE_ENTERED < ADD_MONTHS(TRUNC(sysdate),-12)) AND
NOT EXISTS(SELECT null FROM A_ATEST WHERE
DATE_ENTERED < ADD_MONTHS(TRUNC(sysdate),-1) AND
DATE_ENTERED > ADD_MONTHS(TRUNC(sysdate),-12))
) a
  WHERE
  (SEQ = 1 AND
  DATE_ENTERED >= ADD_MONTHS(TRUNC(sysdate),-1)) AND
  (SEQ = 2 AND
  DATE_ENTERED < ADD_MONTHS(TRUNC(sysdate),-12))

SAMPLE DATA: (Я не вижу способа добавить таблицу, вот так ...)

CUSTOMER, NAME, DATE_ENTERED
100       A     08-APR-20
100       A     01-MAR-20
100       A     01-MAR-20
101       B     09-MAR-20
101       B     07-MAR-19
101       B     01-MAR-19
102       C     04-APR-20
102       C     03-JAN-19
102       C     05-JAN-18

В идеале, набор результатов из моего текущего кода должен отображать:

CUSTOMER, NAME, DATE_ENTERED, SEQ
102       C     04-APR-20     1
102       C     03-JAN-19     2

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

Спасибо!

-dougbert

Ответы [ 3 ]

0 голосов
/ 09 апреля 2020

Я думаю, что это даст вам то, что вы хотите. Ваш вопрос говорит о том, что вы хотите получить список клиентов, но ваши выходные данные предполагают, что вы хотите получить список заказов от этих клиентов.

SELECT CUSTOMER_ID AS "CUSTOMER", NAME, DATE_ENTERED,
  FROM A_ATEST a1
 WHERE a1.DATE_ENTERED >= ADD_MONTHS(TRUNC(sysdate),-24)
   AND EXISTS ( SELECT 1 FROM A_ATEST a3
                 WHERE a3.customer_id  = a1.customer_id
                   AND a3.DATE_ENTERED BETWEEN ADD_MONTHS(TRUNC(sysdate), -24)
                                           AND ADD_MONTHS(TRUNC(sysdate), -12))
   AND NOT EXISTS ( SELECT 1 FROM A_ATEST a2 
                     WHERE a2.customer_id  = a1.customer_id
                       AND DATE_ENTERED < ADD_MONTHS(TRUNC(sysdate), -1) 
                       AND DATE_ENTERED > ADD_MONTHS(TRUNC(sysdate), -12))
   AND EXISTS ( SELECT 1 FROM A_ATEST a4
                 WHERE a4.customer_id  = a1.customer_id
                   AND a4.DATE_ENTERED > ADD_MONTHS(TRUNC(sysdate), -12))

Ключом здесь является то, что ваши подзапросы должны соотносить customer_id с самым внешним A_ATEST стол. То, как вы это написали, в основном означало «и существует заказ от любого клиента от 1 до 12 месяцев go».

0 голосов
/ 09 апреля 2020

В случае, если кто-нибудь ответит на мой вопрос в будущем, я хотел бы поделиться своим окончательным производственным решением. Итак, есть ряд изменений для получения нужного мне результата.

SELECT DISTINCT a1.CUSTOMER_NO AS "CUSTOMER", ci.NAME, MAX(a1.DATE_ENTERED) AS "ORDER DATE", a1.SALESMAN_CODE AS "SALESPERSON"
  FROM CUSTOMER_INFO ci LEFT JOIN CUSTOMER_ORDER a1 ON ci.CUSTOMER_ID = a1.CUSTOMER_NO
 WHERE a1.DATE_ENTERED >= ADD_MONTHS(TRUNC(sysdate), -1)
   AND EXISTS ( SELECT 1 FROM CUSTOMER_ORDER a3
                 WHERE a3.customer_no  = a1.customer_no
                   AND a3.DATE_ENTERED BETWEEN ADD_MONTHS(TRUNC(sysdate), -24)
                                           AND ADD_MONTHS(TRUNC(sysdate), -12))
   AND NOT EXISTS ( SELECT 1 FROM CUSTOMER_ORDER a2 
                     WHERE a2.customer_no  = a1.customer_no
                       AND DATE_ENTERED < ADD_MONTHS(TRUNC(sysdate), -1) 
                       AND DATE_ENTERED > ADD_MONTHS(TRUNC(sysdate), -12))
   AND EXISTS ( SELECT 1 FROM CUSTOMER_ORDER a4
                 WHERE a4.customer_no  = a1.customer_no
                   AND a4.DATE_ENTERED > ADD_MONTHS(TRUNC(sysdate), -24))
GROUP BY a1.CUSTOMER_NO, ci.NAME, a1.SALESMAN_CODE
ORDER BY a1.CUSTOMER_NO, "ORDER DATE"

Еще раз спасибо eaolson и Гордону Линоффу за помощь в доставке меня туда, где мне нужно было go.

0 голосов
/ 08 апреля 2020

Вам нужны заказы за последние два года с разрывом в один год. Это предполагает lag():

select a.*
from (select a.*,
             max(case when prev_de < add_months(date_entered, -12) then 1 else 0 end) over (partition by customer_id) as has_12month_gap
      from (select a.*,
                   lag(date_entered) over (partition by CUSTOMER_ID order by date_entered) as prev_de,
                   max(date_entered) over (partition by customer_id) as max_de
            from A_ATEST a
            where date_entered > add_months(sysdate, -24)
           ) a
     ) a
where max_de > add_months(sysdate, -1) and 
      has_12month_gap = 1;

РЕДАКТИРОВАТЬ:

Выше приведены все транзакции. Только для клиентов, это похожий лог c, но немного проще:

select customer
from (select a.*,
             lag(date_entered) over (partition by CUSTOMER_ID order by date_entered) as prev_de
      from A_ATEST a
      where date_entered > add_months(sysdate, -24)
     ) a
group by customer
where max(date_entered) > add_months(sysdate, -1) and 
      max(case when prev_de < add_months(date_entered, -12) then 1 else 0 end) = 1;
...