暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Oracle 按值合并订单行的分析/模型

askTom 2017-01-30
199

问题描述

如果客户接受发运的最小金额值,则需要编写一个查询,以合并客户的订单行,从而显示其订单行累计最小发运值的日期。如果客户的订单行不符合最小金额,则将日期显示为行的最后发运日期后30天。以下是使用示例数据对手动业务流程的说明。


例如,在LiveSQL上的示例数据中, Cust A有3个订单,共5行,其最小发货额为350。他们的总订单价值是5360。客户B有3个订单, 5行,其最小发货额为750。他们的总订单价值是1875年。

客户A在人工审核时,应合并以下订单:

对于首次装运:
订单1、行1、行2 ,总值350 ,发货日期2017-02-11

第二次装运:
订单1行3 ,订单2行1 ,总值1010 ,发货日期2017-02-21

第三次装运:
订单3行1 ,总值4000 ,发货日期2017-03-31

客户A没有未合并的行。



客户B在人工审核时,应合并以下订单:

对于首次装运:
订单4行1和2 ,订单5行1 ,总值775 ,发货日期2017-02-11

第二次装运:
订单5行2 ,总值1000 ,发货日期2017-02-21

客户B有一个未合并行,订单6行1 ,值100 ,发运日期2017-04-30。


专家解答

这是一个匹配识别的案例!

您需要的是任意数量的订单,直到总订单超过客户的最低值,对吗?

因此,小于最小值的零或更多,然后最多超过一个。在正则表达式中,它是:

  under_min* over_min{0,1}


请注意, over_min需要零个或一个匹配项,以便在结尾处得到未合并的行。

那么,你如何定义这些变量呢?

好的under_min是小于min的行之和, over_min是大于此值的行之和!

  define 
    under_min as sum(line_amt) < min_ship_value,
    over_min as sum(line_amt) >= min_ship_value


在这种情况下,求和就像分析一样,给你计算总数。

您希望按客户拆分行,并按发运日期排序。因此,把它们分别放在分词和分词中。

剩下的就是找出你的专栏。

若要获取组,请使用匹配号()。这将为同一组中的所有行指定一个数字。它为每个新组递增,并为每个新客户重置为1。

要获取组中最后一次发运的日期,您需要over_min的“最终最后一次”发运日期。这会给出此变量最后匹配行的发运日期。对于未合并的订单,没有超过最小发运日期。所以这是空的。因此,这与最后发货日期+30给您期望的结果!

把这些放在一起,你有:

alter session set nls_date_format = 'DD-MON-YYYY';
create table cust (
  cust_id number not null primary key, cust_name varchar2(30) not null,
  min_ship_value number not null
);

create table cust_orders (
  cust_id number not null, order_no number not null, order_line number not null, 
  line_amt number not null, ship_date date not null, 
  constraint fk_orders_cust_id foreign key (cust_id) references cust,
  constraint pk_cust_orders primary key (order_no, order_line)
);

insert into cust values (1,'Cust A',350);
insert into cust values (2,'Cust B',750);

insert into cust_orders values (1,1,1,100,date'2017-01-31');
insert into cust_orders values (1,1,2,250,date'2017-02-11');
insert into cust_orders values (1,1,3,10,date'2017-02-10');
insert into cust_orders values (1,2,1,1000,date'2017-02-21');
insert into cust_orders values (1,3,1,4000,date'2017-03-31');
insert into cust_orders values (2,4,1,175,date'2017-01-31');
insert into cust_orders values (2,4,2,500,date'2017-02-11');
insert into cust_orders values (2,5,1,100,date'2017-02-10');
insert into cust_orders values (2,5,2,1000,date'2017-02-21');
insert into cust_orders values (2,6,1,100,date'2017-03-31');

commit;

select * from (
  select co.*, c.min_ship_value from cust c
  join   cust_orders co
  on     c.cust_id = co.cust_id
)
match_recognize (
  partition by cust_id
  order  by ship_date, order_line
  measures 
    match_number() as mno,
    classifier() as cls,
    sum(line_amt) as tot,
  nvl(final last(over_min.ship_date), last(ship_date)+30) as last_ship_date
  all rows per match
  pattern (under_min* over_min{0,1})
  define 
    under_min as sum(line_amt) < min_ship_value,
    over_min as sum(line_amt) >= min_ship_value
);

CUST_ID  SHIP_DATE    ORDER_LINE  MNO  CLS        TOT    LAST_SHIP_DATE  ORDER_NO  LINE_AMT  MIN_SHIP_VALUE  
1        31-JAN-2017  1           1    UNDER_MIN  100    11-FEB-2017     1         100       350             
1        10-FEB-2017  3           1    UNDER_MIN  110    11-FEB-2017     1         10        350             
1        11-FEB-2017  2           1    OVER_MIN   360    11-FEB-2017     1         250       350             
1        21-FEB-2017  1           2    OVER_MIN   1,000  21-FEB-2017     2         1,000     350             
1        31-MAR-2017  1           3    OVER_MIN   4,000  31-MAR-2017     3         4,000     350             
2        31-JAN-2017  1           1    UNDER_MIN  175    11-FEB-2017     4         175       750             
2        10-FEB-2017  1           1    UNDER_MIN  275    11-FEB-2017     5         100       750             
2        11-FEB-2017  2           1    OVER_MIN   775    11-FEB-2017     4         500       750             
2        21-FEB-2017  2           2    OVER_MIN   1,000  21-FEB-2017     5         1,000     750             
2        31-MAR-2017  1           3    UNDER_MIN  100    30-APR-2017     6         100       750             


如果你想了解更多关于模式匹配的知识,我推荐你阅读基思·湖人的深潜系列。您可以在以下位置找到第一篇文章:

http://oracle-big-data.blogspot.co.uk/2016/03/sql-pattern-matching-deep-dive-part-1.html

PS -感谢您提供清晰的测试用例。虽然我不明白为什么你要整合客户1的订单行1和2 ,在2之前三个发货,所以你肯定会整合这三个订单行吗?

在任何情况下,若要更改这些组合的方式,请通过适当地调整顺序。

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论