在购买其他产品后找到购买产品的客户

时间:2020-02-10 14:00:45

标签: sql oracle

我有一个业务逻辑问题,我不知道如何正确制定sql语句来检索它。为了简化讨论,我将简化业务模型。 我有一张桌子,记录着哪些顾客在哪一天购买了什么产品。

enter image description here

需要找出购买了产品A后购买了产品B的客户实例。我想到了以下查询:

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"

这不是很正确,因为它已经对实例进行了过多计数,因为如果我们看表,客户1在2次购买A之后就购买了B,但我的查询已经计算了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 个答案:

答案 0 :(得分:1)

假设您的年纪在12c或更高,则可以使用pattern matching (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)。

如果您需要在购买其他产品之后找到A之后的B实例,则可以使用排除语法({-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  

答案 1 :(得分:0)

您可以使用聚合和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