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

Oracle 检测不按顺序的记录

askTom 2018-02-23
365

问题描述

我需要在具有日期序列的位置中找到没有事件类型 (join(1)/reship (2)) 的员工。在员工加入另一个位置之前,应首先在某个位置进行加入和退休事件的组合。请注意,员工可以在一个地点退休,在同一日期,他可以在另一个地点加入。

我在表中有以下数据,我需要帮助来编写一个查询,该查询将返回Dataset1,DataSet2,并且不应返回第二个dataset3。


我已经在以下位置创建了数据集
https://livesql.oracle.com/apex/livesql/s/gbg8ozguh66uxkxsialtdwi5h

数据1:
Emp ID Location Date(mm/dd/yyy)Event Type  CREATION_TRAN_SERIAL_NUMBER
123 111  4/3/2017 2
123 222  2/6/2017 2
123 222  1/18/2017 1
123 111  8/1/2016 1


数据2:
Emp ID Location Date Event Type
123 222  1/18/2017 1
123 111  8/1/2016 1



数据3:
Emp ID Location Date Event Type
456 111 3/10/2017 2
456 111 2/6/2017 1
456 333 2/6/2017 2
456 333 1/20/2017 1
456 222 12/14/2016 2
456 111 12/7/2016 2
456 222 12/7/2016 1
456 111 8/22/2016 1


create table T_EVENT_TMP ( 
    EMP_ID                        NUMBER, 
    LOCATION_ID                   NUMBER, 
    EVENT_DATE                    DATE, 
    EVENT_TYPE                    VARCHAR2(4000), 
    CREATION_TRAN_SERIAL_NUMBER   NUMBER 
);

CREATE UNIQUE INDEX PK_T_EVENT_TMP ON T_EVENT_TMP 
(EMP_ID, CREATION_TRAN_SERIAL_NUMBER);

--DataSet1
INSERT INTO T_EVENT_TMP VALUES(123, 111, TO_DATE('08/01/2016','mm/dd/yyyy'), 1, 1);
INSERT INTO T_EVENT_TMP VALUES(123, 222, TO_DATE('01/18/2017','mm/dd/yyyy'), 1, 2);
INSERT INTO T_EVENT_TMP VALUES(123, 222, TO_DATE('02/06/2017','mm/dd/yyyy'), 2, 3);
INSERT INTO T_EVENT_TMP VALUES(123, 111, TO_DATE('04/03/2017','mm/dd/yyyy'), 2, 4);


--DataSet2
INSERT INTO T_EVENT_TMP VALUES(456, 333, TO_DATE('08/01/2016','mm/dd/yyyy'), 1, 5);
INSERT INTO T_EVENT_TMP VALUES(456, 444, TO_DATE('01/18/2017','mm/dd/yyyy'), 1, 6);

--DataSet3
INSERT INTO T_EVENT_TMP VALUES(777, 111, TO_DATE('08/22/2016','mm/dd/yyyy'), 1, 7);
INSERT INTO T_EVENT_TMP VALUES(777, 222, TO_DATE('12/07/2016','mm/dd/yyyy'), 1, 8);
INSERT INTO T_EVENT_TMP VALUES(777, 111, TO_DATE('12/07/2016','mm/dd/yyyy'), 2, 9);
INSERT INTO T_EVENT_TMP VALUES(777, 222, TO_DATE('12/14/2016','mm/dd/yyyy'), 2, 10);
INSERT INTO T_EVENT_TMP VALUES(777, 333, TO_DATE('01/20/2017','mm/dd/yyyy'), 1, 11);
INSERT INTO T_EVENT_TMP VALUES(777, 333, TO_DATE('02/06/2017','mm/dd/yyyy'), 2, 12);
INSERT INTO T_EVENT_TMP VALUES(777, 111, TO_DATE('02/06/2017','mm/dd/yyyy'), 1, 13);
INSERT INTO T_EVENT_TMP VALUES(777, 111, TO_DATE('03/10/2017','mm/dd/yyyy'), 2, 14);


我非常感谢你的帮助。
问候
希克

专家解答

因此,对于特定员工,当您按日期和序列号订购行时,您期望:

-在联接 (类型1) 和retires (类型2) 之间交替的行
-每个退休行应具有与上一个联接相同的位置

对吗?

如果是这样,你有一个问题,如果:

-一行中有两个或多个联接
-连续有两个或两个以上的退休人员
-您有一个加入,然后在其他位置退休

用12c的匹配识别很容易找到这些。为每个模式变量创建模式变量。然后搜索这些模式中的任何一种或多种出现。

将示例扩展为包括不匹配的退休提供:

INSERT INTO T_EVENT VALUES(777, 888, TO_DATE('04/10/2017','mm/dd/yyyy'), 1, 15);
INSERT INTO T_EVENT VALUES(777, 999, TO_DATE('05/10/2017','mm/dd/yyyy'), 2, 16);

select * 
from t_event match_recognize (
  partition by emp_id
  order by event_date, creation_tran_serial_number
  measures
    match_number() mno,
    classifier() cls
  all rows per match with unmatched rows
  pattern ( ( join_{2,} | retire{2,} | (join_ retire_mismatch) )+ )
  define
    join_ as event_type = 1,
    retire as event_type = 2,
    retire_mismatch as event_type = 2 and prev(location_id) <> location_id 
);

    EMP_ID EVENT_DAT CREATION_TRAN_SERIAL_NUMBER        MNO CLS             LOCATION_ID EVENT_TYPE
---------- --------- --------------------------- ---------- --------------- ----------- ----------
       123 01-AUG-16                           1          1 JOIN_                   111 1
       123 18-JAN-17                           2          1 JOIN_                   222 1
       123 06-FEB-17                           3          1 RETIRE                  222 2
       123 03-APR-17                           4          1 RETIRE                  111 2
       456 01-AUG-16                           5          1 JOIN_                   333 1
       456 18-JAN-17                           6          1 JOIN_                   444 1
       777 22-AUG-16                           7          1 JOIN_                   111 1
       777 07-DEC-16                           8          1 JOIN_                   222 1
       777 07-DEC-16                           9          1 RETIRE                  111 2
       777 14-DEC-16                          10          1 RETIRE                  222 2
       777 20-JAN-17                          11                                    333 1
       777 06-FEB-17                          12                                    333 2
       777 06-FEB-17                          13                                    111 1
       777 10-MAR-17                          14                                    111 2
       777 10-APR-17                          15          2 JOIN_                   888 1
       777 10-MAY-17                          16          2 RETIRE_MISMATCH         999 2


我已经包括了不匹配的行,以帮助查看发生了什么。如果只需要失败的行,请从 “每次匹配的所有行” 中删除 “具有不匹配的行”。

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

评论