Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/68.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SAP HANA SQL匹配字符串模式和组合_Sql_String_Pattern Matching_Sap_Hana - Fatal编程技术网

SAP HANA SQL匹配字符串模式和组合

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”购买了活动中提到的产

我正在使用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”购买了活动中提到的产品组合,因此它将符合这两个活动的要求。

预期结果:
客户销售活动
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

请帮我找到更好的解决办法。非常感谢您的任何想法。

如果您允许更改存储活动中哪些组的定义的方式,则以下解决方案是可能的:

  • 活动由一组组组定义
  • 这些组包含产品ID或名称
  • 任何组都可以被视为
    组,这意味着要匹配此组,必须从该组购买至少一种产品。或者,组可以是
    组,这意味着需要购买与组匹配的所有产品
  • 这看起来是这样的:

    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  
    
    现在,我们可以简单地了解

    • 运动
    • 其中每个小组包括:
    • 群体类型,
    • 有多少团体参与了这项活动
    • 每组有多少种产品
    用于此的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                
    
    其余部分有点乏味,但不太复杂。 我们需要
    -计算每个客户对每个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)。仅使用的组合选项为和、或。