【问题标题】:Oracle 12c - sql to find out of order rowsOracle 12c - 用于查找乱序行的 sql
【发布时间】:2019-01-14 16:13:25
【问题描述】:

我有一个包含以下列的表格:

FILE_NAME VARCHAR2(30);
STATUS VARCHAR2(2);
DEPT_ID NUMBER;
DEPT_SUB_ID NUMBER;
CREATE_DATE DATE;

样本数据:

FILE_NAME                 STATUS  DEPT_ID   DEPT_SUB_ID  CREATE_DATE
---------                 ------- --------  -----------  ----------
TEST_20180806222127       C       1         10           07-AUG-18 01.04.47.821795000 AM
TEST_20180806221940       C       1         10           07-AUG-18 04.12.20.957400000 AM
TEST_20180806221733       C       1         10           07-AUG-18 03.35.27.809494000 AM
TEST_20180805202020       C       1         20           06-AUG-18 02.24.47.821795000 AM
TEST_20180805201640       C       1         20           06-AUG-18 00.42.20.957400000 AM
TEST_20180805201530       C       1         20           06-AUG-18 03.55.27.809494000 AM

FILE_NAME 包括:<TYPE>_<DATETIME> 我想为每个DEPT_ID、DEPT_SUB_ID 编写一个查询,以确定哪些带有STATUS = 'C' 的文件是根据FILE_NAME 和CREATE_DATE 字段上的<DATETIME> 乱序创建的。在此示例中,对于DEPT_SUB_ID = 10,文件TEST_20180806222127 是在基于文件名上的DATE_TIME 的其他2 之前创建的,因此我只需要在DEPT_SUB_ID = 10 的结果中返回此文件名。对于DEPT_SUB_ID = 20,结果应包含TEST_20180805201640 和TEST_20180805202020,因为两者都是在TEST_20180805201530 之前创建的,这被认为是无序的。

查询的预期结果将输出在运行顺序之前创建的所有文件名。

【问题讨论】:

    标签: sql oracle select oracle12c


    【解决方案1】:

    您可以为每一行分配两个排名,一个基于嵌入在文件名中的时间戳的顺序,或者另一个基于创建日期的顺序:

    select yt.*,
      row_number() over (partition by dept_id, dept_sub_id
        order by to_date(substr(file_name, -14), 'YYYYMMDDHH24MISS')) as rn_file_name,
      row_number() over (partition by dept_id, dept_sub_id
        order by create_date) as rn_create_date
    from your_table yt;
    
    FILE_NAME           S    DEPT_ID DEPT_SUB_ID CREATE_DATE                   RN_FILE_NAME RN_CREATE_DATE
    ------------------- - ---------- ----------- ----------------------------- ------------ --------------
    TEST_20180806221733 C          1          10 2018-08-07 03:35:27.809494000            1              2
    TEST_20180806221940 C          1          10 2018-08-07 04:12:20.957400000            2              3
    TEST_20180806222127 C          1          10 2018-08-07 01:04:47.821795000            3              1
    TEST_20180805201530 C          1          20 2018-08-06 03:55:27.809494000            1              3
    TEST_20180805201640 C          1          20 2018-08-06 00:42:20.957400000            2              1
    TEST_20180805202020 C          1          20 2018-08-06 02:24:47.821795000            3              2
    

    然后过滤以查看不匹配:

    select file_name, status, dept_id, dept_sub_id, create_date
    from (
      select yt.*,
        row_number() over (partition by dept_id, dept_sub_id
          order by to_date(substr(file_name, -14), 'YYYYMMDDHH24MISS')) as rn_file_name,
        row_number() over (partition by dept_id, dept_sub_id
          order by create_date) as rn_create_date
      from your_table yt
    )
    where rn_file_name > rn_create_date;
    
    FILE_NAME           S    DEPT_ID DEPT_SUB_ID CREATE_DATE                  
    ------------------- - ---------- ----------- -----------------------------
    TEST_20180806222127 C          1          10 2018-08-07 01:04:47.821795000
    TEST_20180805201640 C          1          20 2018-08-06 00:42:20.957400000
    TEST_20180805202020 C          1          20 2018-08-06 02:24:47.821795000
    

    如果您不想一次看到所有特定 ID 或子 ID,可以在内部或外部查询中添加过滤器。

    【讨论】:

    • 你赢了我:)
    • 不得不最终发生 *8-)
    猜你喜欢
    • 1970-01-01
    • 2020-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-10
    • 2019-08-21
    • 2014-04-21
    • 2018-10-26
    相关资源
    最近更新 更多