【问题标题】:Selecting valid entry and exit records选择有效的进入和退出记录
【发布时间】:2017-04-28 16:25:52
【问题描述】:

以下是我的表格中的示例

F_ID     R_ID       DATE    Col_A   Col_B   Col_C  Day_Rec  Update_No
 12      158      20161008    01      99     99     1        -
 12      158      20161012    01      01     99     1        -
 12      158      20161019    01      02     10     1        -
 12      158      20161019    99      01     10     2        1
 12      158      20161019    99      02     10     2        2
 12      160      20161006    01      99     01     1        -
 12      160      20161006    01      99     02     2        1
 12      160      20161011    99      01     99     1        -
 17      167      20161013    99      01     01     1        - 
 17      167      20161016    99      02     99     1        -
 17      167      20161020    02      01     10     1        -
 17      174      20161010    99      01     01     1        -
 17      174      20161012    01      02     11     1        -
 17      174      20161017    99      02     10     1        -
 17      174      20161017    99      96     10     2        1
 17      174      20161017    99      07     10     2        2
 17      174      20161017    99      99     10     2        3

对于每个 F_ID,R_ID:

When Col_A or Col_B = '01' and Col_C <>'10' - **It is an entry record**
When Col_C = '10' - **It is an exit record**

Day_Rec = 1 means it is the first entry on that date
Day_Rec = 2 means it is the modification on the same date

Update_No - Incremental modification tracker

Update_No is missing when Day_Rec = 1 because its not a modification 
Update_No = 1 or 2 or 3..... when Day_Rec = 2 modified multiple times on same date

同一日期可以有多个修改,但 Day_Rec 仍然只有 2 个。多个更新由 Update_No 跟踪

这里的逻辑是

1. Select the earliest valid entry record. 
   If there is a modification on that earliest date select the entry record with Day_Rec = 2 and highest Update_No 
   **and** 
2. Select the latest exit record.
   If there is a modification on that latest date select the exit record with Day_Rec = 2 and highest Update_No  for each F_ID, R_ID

我想选择这样我就可以为每个 F_ID 和 R_ID 获得一个有效的进入记录和一个有效的退出记录。仅当每个 F_ID 和 R_ID 都有有效的进入和退出记录时

F_ID   R_ID    DATE     Col_A   Col_B   Col_C  Day_Rec Update_No
12     158    20161008    01      99     99      1       -      ->  Entry record
12     158    20161019    99      02     10      2       2      ->  Exit Record
17     167    20161013    99      01     01      1       -      ->  Entry record
17     167    20161020    02      01     10      1       -      ->  Exit Record
17     174    20161010    99      01     01      1       -      ->  Entry record
17     174    20161017    99      99     10      2       3      ->  Exit Record

我有以下查询来按日期获取排序入口和出口记录

SELECT * FROM (
SELECT your_table.*, ROW_NUMBER() OVER(PARTITION BY F_ID, R_ID order by DATE) as rn, 'Entry record' as rec FROM your_table WHERE (Col_A = '01' or Col_B = '01') and Col_C <> '10'
    union all
SELECT your_table.*, ROW_NUMBER() OVER(PARTITION BY F_ID, R_ID order by DATE DESC) as rn, 'Exit record' as rec FROM your_table WHERE Col_C = '10'
) t3
where rn = 1
ORDER BY F_ID, R_ID, DATE

但我如何考虑“Day_Rec”或“Update_No”字段。此外,它不会让我知道“仅当每个 F_ID 和 R_ID 都存在进入和退出记录时”条件

更新:

我在选择查询的开头尝试了“Case when”,但没有运气。如果 Day_Rec = 2 在进入和退出记录的 where 条件内,我似乎无法获得如何选择 max(Update_No)

【问题讨论】:

    标签: sql oracle select union


    【解决方案1】:
    1. 根据f_idr_id 选择第一个条目。然后外部加入那些f_idr_id和日期的最新修改。 (从 12c 开始,您可以为此使用 OUTER APPLY。)
    2. 对出口做同样的事情。
    3. UNION ALL 两个查询。
    4. 获取结果并仅保留结果集中有两行的f_idr_id

    查询:

    select f_id, r_id, dte, col_a, col_b, col_c, day_rec, update_no 
    from
    (
      select 
        both.*,
        count(*) over (partition by f_id, r_id) as cnt
      from
      (
        select 
          e.f_id, 
          e.r_id, 
          e.dte, 
          coalesce(m.col_a, e.col_a) as col_a,
          coalesce(m.col_a, e.col_a) as col_b,
          coalesce(m.col_a, e.col_a) as col_c,
          coalesce(m.day_rec, e.day_rec) as day_rec,
          m.update_no
        from
        (
          select
            your_table.*,
            row_number() over(partition by f_id, r_id order by dte) as rn
          from your_table 
          where (col_a = '01' or col_b = '01') and col_c <> '10' and day_rec = 1
        ) e
        left join
        (
          select
            your_table.*,
            row_number() over(partition by f_id, r_id, dte order by update_no desc) as rn
          from your_table 
          where (col_a = '01' or col_b = '01') and col_c <> '10' and day_rec > 1
        ) m on m.f_id = e.f_id and m.r_id = e.r_id and m.dte = e.dte and m.rn = 1
        where e.rn = 1
        union all
        select 
          e.f_id, 
          e.r_id, 
          e.dte, 
          coalesce(m.col_a, e.col_a) as col_a,
          coalesce(m.col_a, e.col_a) as col_b,
          coalesce(m.col_a, e.col_a) as col_c,
          coalesce(m.day_rec, e.day_rec) as day_rec,
          m.update_no
        from
        (
          select
            your_table.*,
            row_number() over(partition by f_id, r_id order by dte) as rn
          from your_table 
          where col_c = '10' and day_rec = 1
        ) e
        left join
        (
          select
            your_table.*,
            row_number() over(partition by f_id, r_id, dte order by update_no desc) as rn
          from your_table 
          where col_c = '10' and day_rec > 1
        ) m on m.f_id = e.f_id and m.r_id = e.r_id and m.dte = e.dte and m.rn = 1
        where e.rn = 1
      ) both
    )
    where cnt = 2;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-01-30
      • 1970-01-01
      • 2013-04-05
      • 2017-09-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多