Найти покупателя, покупающего товар после покупки другого - PullRequest
0 голосов
/ 10 февраля 2020

У меня вопрос по бизнес-логике c, и я не знаю, как правильно сформулировать оператор sql для его получения. Я упросту бизнес-модель для облегчения обсуждения. У меня есть таблица с записью, какие клиенты купили какой продукт и в какой день.

enter image description here

Необходимо выяснить случаи, когда клиенты ) которые приобрели продукт B после приобретения продукта A. Я задал следующий вопрос:

select t."Customer",t."Date" "Date2", t."Product" "Product2",a.*
from
(
select "Customer","Date", "Product"
from test2 where "Product"='A'
) a,
test2 t
where a."Customer"= t."Customer" and t."Product"='B' and t."Date">=a."Date"

Это не совсем верно, так как он пересчитал количество экземпляров, потому что, если мы посмотрим на таблицу, клиент Я купил B после покупки A в 2 случаях, но мой запрос насчитал 3 раза

enter image description here

Случай, который я обвел, не должен учитываться. Есть ли способ это исправить? Для вашего удобства я приложил скрипт для создания таблицы TEST2.

  CREATE TABLE  "TEST2" 
   (    "Customer" VARCHAR2(26 BYTE), 
    "Date" DATE, 
    "Product" VARCHAR2(26 BYTE)
   );

Insert into  TEST2 ("Customer","Date","Product") values ('1',to_date('07-AUG-18','DD-MON-RR'),'A');
Insert into  TEST2 ("Customer","Date","Product") values ('1',to_date('07-AUG-18','DD-MON-RR'),'B');
Insert into  TEST2 ("Customer","Date","Product") values ('1',to_date('17-AUG-18','DD-MON-RR'),'A');
Insert into  TEST2 ("Customer","Date","Product") values ('1',to_date('27-SEP-18','DD-MON-RR'),'B');
Insert into  TEST2 ("Customer","Date","Product") values ('2',to_date('26-SEP-18','DD-MON-RR'),'A');
Insert into  TEST2 ("Customer","Date","Product") values ('3',to_date('01-OCT-18','DD-MON-RR'),'C');

Ответы [ 2 ]

1 голос
/ 10 февраля 2020

Если вы на 12 c или выше, вы можете сделать это с сопоставлением с образцом (match_recognize) :

CREATE TABLE TEST2 (    
  customer      VARCHAR2(26 BYTE), 
  purchase_date DATE, 
  Product       VARCHAR2(26 BYTE)
);

Insert into TEST2 (customer,purchase_date,product) values ('1',to_date('07-AUG-18','DD-MON-RR'),'A');
Insert into TEST2 (customer,purchase_date,product) values ('1',to_date('07-AUG-18','DD-MON-RR'),'B');
Insert into TEST2 (customer,purchase_date,product) values ('1',to_date('17-AUG-18','DD-MON-RR'),'A');
Insert into TEST2 (customer,purchase_date,product) values ('1',to_date('27-SEP-18','DD-MON-RR'),'B');
Insert into TEST2 (customer,purchase_date,product) values ('2',to_date('26-SEP-18','DD-MON-RR'),'A');
Insert into TEST2 (customer,purchase_date,product) values ('3',to_date('01-OCT-18','DD-MON-RR'),'C');
commit;

select * from test2
match_recognize (
  partition by customer
  order by purchase_date, product
  measures
    proda.purchase_date prod_a_date,
    prodb.purchase_date prod_b_date
  pattern ( proda prodb )
  define
    proda as product = 'A',
    prodb as product = 'B'
);

CUSTOMER    PROD_A_DATE             PROD_B_DATE            
1           07-AUG-2018 00:00:00    07-AUG-2018 00:00:00    
1           17-AUG-2018 00:00:00    27-SEP-2018 00:00:00   

Это говорит:

  • Для каждого клиента (partition by customer)
  • Сортировка по дате покупки и продукту (order by purchase_date, product)
  • Найдите экземпляры продукта A, за которыми сразу следует продукт B (pattern ( proda prodb ))
  • В разделе define указано, что такое продукты

Шаблон является регулярным выражением. Вы можете переопределить переменные для поиска любого продукта, который вы хотите (или сделать так, чтобы значения продукта связывали переменные - proda as product = :bindvar).

Если вам нужно найти экземпляры B после A с промежуточными покупками других продуктов, Вы можете использовать синтаксис исключения ({-var-}):

insert into TEST2 (customer,purchase_date,product) 
  values ('1',to_date('20-SEP-18','DD-MON-RR'),'C');

select * from test2
match_recognize (
  partition by customer
  order by purchase_date, product
  measures
    proda.purchase_date prod_a_date,
    prodb.purchase_date prod_b_date
  pattern ( proda {-otherprod*-} prodb )
  define
    proda as product = 'A',
    prodb as product = 'B',
    otherprod as product not in ( 'A', 'B' )
);

CUSTOMER    PROD_A_DATE             PROD_B_DATE            
1           07-AUG-2018 00:00:00    07-AUG-2018 00:00:00    
1           17-AUG-2018 00:00:00    27-SEP-2018 00:00:00  
0 голосов
/ 10 февраля 2020

Вы можете использовать агрегацию и предложение having:

select customer
from test2
group by customer
having min(case when product = 'A' then date end) < max(case when product = 'B' then date end);

Если вам нужны даты, просто добавьте функции из having в select.

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