我有一个业务逻辑问题,我不知道如何正确制定sql语句来检索它。为了简化讨论,我将简化业务模型。 我有一张桌子,记录着哪些顾客在哪一天购买了什么产品。
需要找出购买了产品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次
我圈出的实例不算在内。 有没有办法来解决这个问题? 为了方便起见,我附加了一个脚本来创建表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');
答案 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
)排序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
。