SAP HANA SQL匹配字符串模式和组合
我正在使用HANA,并试图根据列中的多个值组合从表中提取数据:SAP HANA SQL匹配字符串模式和组合,sql,string,pattern-matching,sap,hana,Sql,String,Pattern Matching,Sap,Hana,我正在使用HANA,并试图根据列中的多个值组合从表中提取数据: 下面是我的客户表布局: 表A: 客户产品 ABC P1 ABC P2 ABC P3 ABC G2 ABC G4 ABC G6 ABC G5 以下是销售活动规则: 组合: 活动\名称产品\购买的产品 活动1(P1、P2和P3) 活动2(G2或G4)和G6 如果客户购买了所有产品P1、P2和P3,则其有资格参加活动1。 如果客户从(G2或G4)和G6购买任何产品,则其将有资格参加活动2。 在本例中,由于客户“ABC”购买了活动中提到的产
下面是我的客户表布局:
表A:
客户产品 ABC P1
ABC P2
ABC P3
ABC G2
ABC G4
ABC G6
ABC G5
以下是销售活动规则:
组合:
活动\名称产品\购买的产品
活动1(P1、P2和P3)
活动2(G2或G4)和G6
如果客户购买了所有产品P1、P2和P3,则其有资格参加活动1。
如果客户从(G2或G4)和G6购买任何产品,则其将有资格参加活动2。
在本例中,由于客户“ABC”购买了活动中提到的产品组合,因此它将符合这两个活动的要求。
预期结果:
客户销售活动
ABC活动1
ABC活动2
以下是我迄今为止执行的步骤:
步骤1:我提取了在客户级别购买的所有产品。 步骤2:我将客户购买的所有产品汇总在一行中,用逗号分隔。
步骤3:在案例陈述中手动给出所有可能的组合,并为每个活动设置一个标志栏,以确定客户是否购买了任何符合条件的销售活动。
步骤4:如果标志为“Y”,则我提取了相应的活动名称。
但如果产品数量增加,则无法得出上述步骤3。
步骤2结果:
CustomerP\u COMBOG\u COMBO
ABC#,1,P1,P2,P3#,1,G2,G4,G5,G6
SELECT DISTINCT
B.CUSTOMER
CASE WHEN P_COMBO ='#,1,P1,P2,P3' THEN 'Y' ELSE 'N' END) AS campaign1_flag,
(CASE
WHEN G_COMBO ='#,1,G2,G6' THEN 'Y'
WHEN G_COMBO ='#,1,G4,G6' THEN 'Y'
WHEN G_COMBO ='#,1,G2,G5,G6' THEN 'Y'
WHEN G_COMBO ='#,1,G4,G5,G6' THEN 'Y'
WHEN G_COMBO ='#,1,G2,G4,G5,G6' THEN 'Y'
ELSE 'N'
END) AS Campaign2_flag
FROM (
SELECT DISTINCT
A.CUSTOMER ,
( MAX(CASE WHEN A.PRODUCT= '1' THEN A.PRODUCT ELSE '#' END)
|| MAX(CASE WHEN A.PRODUCT= 'P1' THEN ',' || A.PRODUCT ELSE '' END)
|| MAX(CASE WHEN A.PRODUCT= 'P2' THEN ',' || A.PRODUCT ELSE '' END)
|| MAX(CASE WHEN A.PRODUCT= 'P3' THEN ',' || A.PRODUCT ELSE '' END)
) AS P_COMBO ,
( MAX(CASE WHEN A.PRODUCT= '1' THEN A.PRODUCT ELSE '#' END)
|| MAX(CASE WHEN A.PRODUCT= 'G2' THEN ',' || A.PRODUCT ELSE '' END)
|| MAX(CASE WHEN A.PRODUCT= 'G4' THEN ',' || A.PRODUCT ELSE '' END)
|| MAX(CASE WHEN A.PRODUCT= 'G5' THEN ',' || A.PRODUCT ELSE '' END)
|| MAX(CASE WHEN A.PRODUCT= 'G6' THEN ',' || A.PRODUCT ELSE '' END)
) AS G_COMBO
FROM
(SELECT DISTINCT CUSTOMER,PRODUCT FROM customer) A
GROUP BY CUSTOMER,2,3
) B
步骤4结果:客户投诉1_标志活动2_标志
ABC YY
SELECT DISTINCT
B.CUSTOMER
CASE WHEN P_COMBO ='#,1,P1,P2,P3' THEN 'Y' ELSE 'N' END) AS campaign1_flag,
(CASE
WHEN G_COMBO ='#,1,G2,G6' THEN 'Y'
WHEN G_COMBO ='#,1,G4,G6' THEN 'Y'
WHEN G_COMBO ='#,1,G2,G5,G6' THEN 'Y'
WHEN G_COMBO ='#,1,G4,G5,G6' THEN 'Y'
WHEN G_COMBO ='#,1,G2,G4,G5,G6' THEN 'Y'
ELSE 'N'
END) AS Campaign2_flag
FROM (
SELECT DISTINCT
A.CUSTOMER ,
( MAX(CASE WHEN A.PRODUCT= '1' THEN A.PRODUCT ELSE '#' END)
|| MAX(CASE WHEN A.PRODUCT= 'P1' THEN ',' || A.PRODUCT ELSE '' END)
|| MAX(CASE WHEN A.PRODUCT= 'P2' THEN ',' || A.PRODUCT ELSE '' END)
|| MAX(CASE WHEN A.PRODUCT= 'P3' THEN ',' || A.PRODUCT ELSE '' END)
) AS P_COMBO ,
( MAX(CASE WHEN A.PRODUCT= '1' THEN A.PRODUCT ELSE '#' END)
|| MAX(CASE WHEN A.PRODUCT= 'G2' THEN ',' || A.PRODUCT ELSE '' END)
|| MAX(CASE WHEN A.PRODUCT= 'G4' THEN ',' || A.PRODUCT ELSE '' END)
|| MAX(CASE WHEN A.PRODUCT= 'G5' THEN ',' || A.PRODUCT ELSE '' END)
|| MAX(CASE WHEN A.PRODUCT= 'G6' THEN ',' || A.PRODUCT ELSE '' END)
) AS G_COMBO
FROM
(SELECT DISTINCT CUSTOMER,PRODUCT FROM customer) A
GROUP BY CUSTOMER,2,3
) B
请帮我找到更好的解决办法。非常感谢您的任何想法。如果您允许更改存储活动中哪些组的定义的方式,则以下解决方案是可能的:
或组,这意味着要匹配此组,必须从该组购买至少一种产品。或者,组可以是和组,这意味着需要购买与组匹配的所有产品
create column table camp_grps
(camp NVARCHAR(20) not null
, grp integer not null
, grp_type NVARCHAR(3) not null
, product NVARCHAR(20) not null);
insert into camp_grps values
('Campaign 1', '1', 'AND', 'P1');
insert into camp_grps values
('Campaign 1', '1', 'AND', 'P2');
insert into camp_grps values
('Campaign 1', '1', 'AND', 'P3');
insert into camp_grps values
('Campaign 2', '1', 'OR', 'G2');
insert into camp_grps values
('Campaign 2', '1', 'OR', 'G4');
insert into camp_grps values
('Campaign 2', '2', 'AND', 'G6');
CAMP | GRP | GRP_TYPE| PRODUCT
-----------|--------|---------|-------
Campaign 1 | 1 | AND | P1
Campaign 1 | 1 | AND | P2
Campaign 1 | 1 | AND | P3
Campaign 2 | 1 | OR | G2
Campaign 2 | 1 | OR | G4
Campaign 2 | 2 | AND | G6
现在,我们可以简单地了解
- 运动
- 其中每个小组包括:
- 群体类型,
- 有多少团体参与了这项活动
- 每组有多少种产品李>
select
camp
, grp
, grp_type
, count(distinct grp) over
(partition by camp) camp_grp_cnt
, count(*) prd_cnt
from
camp_grps
group by
camp, grp, grp_type;
CAMP |GRP |GRP_TYPE |CAMP_GRP_CNT |PRD_CNT
------------|-------|-----------|---------------|-------
Campaign 1 |1 |AND |1 |3
Campaign 2 |1 |OR |2 |2
Campaign 2 |2 |AND |2 |1
with grp_ref as
(select
camp
, grp
, grp_type
, count(distinct grp) over
(partition by camp) camp_grp_cnt
, count(*) prd_cnt
from
camp_grps
group by
camp, grp, grp_type),
grp_match as
(select
p.customer, p.product
, gr.camp camp_ref, gr.grp grp_ref, gr.grp_type grp_type_ref, gr.prd_cnt prd_cnt_ref
, gr.camp_grp_cnt
, count(*) over
(partition by p.customer, cg.camp, gr.grp) camp_total_matches
from
purchases p
left outer join camp_grps cg
on p.product = cg.product
inner join grp_ref gr
on (cg.camp, cg.grp) = (gr.camp, gr.grp)),
match_cnter as
(select
customer, product
, camp_ref, grp_ref, grp_type_ref, prd_cnt_ref, camp_total_matches
, camp_grp_cnt
, case
when grp_type_ref = 'AND'
and ((camp_total_matches - prd_cnt_ref) >= 0) then
'AND grp matched'
when grp_type_ref = 'OR'
and (camp_total_matches > 1) then
'OR grp matched'
end matched_grp_info
, case
when grp_type_ref = 'AND'
and ((camp_total_matches - prd_cnt_ref) >= 0) then
1
when grp_type_ref = 'OR'
and (camp_total_matches > 1) then
1
end matched_grp
from
grp_match)
select
customer, camp_ref, SUM(matched_grp), MIN(camp_grp_cnt)
from
match_cnter
group by
customer, camp_ref;
CUSTOMER |CAMP_REF |SUM(MATCHED_GRP) | MIN(CAMP_GRP_CNT)
------------|-----------|-------------------|---------------------------
ABC |Campaign 1 |3 |1
ABC |Campaign 2 |3 |2
XYZ |Campaign 1 |? |1
其余部分有点乏味,但不太复杂。
我们需要-计算每个客户对每个grp的匹配购买数量 -根据组的类型(
和
/或
),当与组的匹配数大于0(或
组)或至少是组中的产品数(和
组)时,我们需要将组计算为匹配
组合的SQL如下所示:
select
camp
, grp
, grp_type
, count(distinct grp) over
(partition by camp) camp_grp_cnt
, count(*) prd_cnt
from
camp_grps
group by
camp, grp, grp_type;
CAMP |GRP |GRP_TYPE |CAMP_GRP_CNT |PRD_CNT
------------|-------|-----------|---------------|-------
Campaign 1 |1 |AND |1 |3
Campaign 2 |1 |OR |2 |2
Campaign 2 |2 |AND |2 |1
with grp_ref as
(select
camp
, grp
, grp_type
, count(distinct grp) over
(partition by camp) camp_grp_cnt
, count(*) prd_cnt
from
camp_grps
group by
camp, grp, grp_type),
grp_match as
(select
p.customer, p.product
, gr.camp camp_ref, gr.grp grp_ref, gr.grp_type grp_type_ref, gr.prd_cnt prd_cnt_ref
, gr.camp_grp_cnt
, count(*) over
(partition by p.customer, cg.camp, gr.grp) camp_total_matches
from
purchases p
left outer join camp_grps cg
on p.product = cg.product
inner join grp_ref gr
on (cg.camp, cg.grp) = (gr.camp, gr.grp)),
match_cnter as
(select
customer, product
, camp_ref, grp_ref, grp_type_ref, prd_cnt_ref, camp_total_matches
, camp_grp_cnt
, case
when grp_type_ref = 'AND'
and ((camp_total_matches - prd_cnt_ref) >= 0) then
'AND grp matched'
when grp_type_ref = 'OR'
and (camp_total_matches > 1) then
'OR grp matched'
end matched_grp_info
, case
when grp_type_ref = 'AND'
and ((camp_total_matches - prd_cnt_ref) >= 0) then
1
when grp_type_ref = 'OR'
and (camp_total_matches > 1) then
1
end matched_grp
from
grp_match)
select
customer, camp_ref, SUM(matched_grp), MIN(camp_grp_cnt)
from
match_cnter
group by
customer, camp_ref;
CUSTOMER |CAMP_REF |SUM(MATCHED_GRP) | MIN(CAMP_GRP_CNT)
------------|-----------|-------------------|---------------------------
ABC |Campaign 1 |3 |1
ABC |Campaign 2 |3 |2
XYZ |Campaign 1 |? |1
结果如下所示:
select
camp
, grp
, grp_type
, count(distinct grp) over
(partition by camp) camp_grp_cnt
, count(*) prd_cnt
from
camp_grps
group by
camp, grp, grp_type;
CAMP |GRP |GRP_TYPE |CAMP_GRP_CNT |PRD_CNT
------------|-------|-----------|---------------|-------
Campaign 1 |1 |AND |1 |3
Campaign 2 |1 |OR |2 |2
Campaign 2 |2 |AND |2 |1
with grp_ref as
(select
camp
, grp
, grp_type
, count(distinct grp) over
(partition by camp) camp_grp_cnt
, count(*) prd_cnt
from
camp_grps
group by
camp, grp, grp_type),
grp_match as
(select
p.customer, p.product
, gr.camp camp_ref, gr.grp grp_ref, gr.grp_type grp_type_ref, gr.prd_cnt prd_cnt_ref
, gr.camp_grp_cnt
, count(*) over
(partition by p.customer, cg.camp, gr.grp) camp_total_matches
from
purchases p
left outer join camp_grps cg
on p.product = cg.product
inner join grp_ref gr
on (cg.camp, cg.grp) = (gr.camp, gr.grp)),
match_cnter as
(select
customer, product
, camp_ref, grp_ref, grp_type_ref, prd_cnt_ref, camp_total_matches
, camp_grp_cnt
, case
when grp_type_ref = 'AND'
and ((camp_total_matches - prd_cnt_ref) >= 0) then
'AND grp matched'
when grp_type_ref = 'OR'
and (camp_total_matches > 1) then
'OR grp matched'
end matched_grp_info
, case
when grp_type_ref = 'AND'
and ((camp_total_matches - prd_cnt_ref) >= 0) then
1
when grp_type_ref = 'OR'
and (camp_total_matches > 1) then
1
end matched_grp
from
grp_match)
select
customer, camp_ref, SUM(matched_grp), MIN(camp_grp_cnt)
from
match_cnter
group by
customer, camp_ref;
CUSTOMER |CAMP_REF |SUM(MATCHED_GRP) | MIN(CAMP_GRP_CNT)
------------|-----------|-------------------|---------------------------
ABC |Campaign 1 |3 |1
ABC |Campaign 2 |3 |2
XYZ |Campaign 1 |? |1
根据CUSTOMER
和CAMP\u REF
(活动参考)我们可以看到有多少组活动已经匹配(SUM(matched\u GRP)
)以及有多少组活动需要匹配(MIN(CAMP\u GRP\u CNT)
)
客户
ABC
符合活动1和活动2的条件,而客户XYZ
未匹配任何组(请参见结果中的?
为NULL
。未来预计有多少组合?或
组中的产品是否相似(例如相同的产品类别)或完全任意?还有其他组合选项吗(或/XOR
)?组合可能很多,但不是固定的。或组中的产品相似,属于相同的产品类别,即(G1或G2或G3)。仅使用的组合选项为和、或。