【问题标题】:Oracle: Selecting current and most recent previous value (Appending new columns)Oracle:选择当前和最近的先前值(附加新列)
【发布时间】:2021-03-19 03:57:07
【问题描述】:

我尝试了很多小时不同的替代方案,但没有成功。 我正在使用员工数据集,该数据集在每次数据更改后创建一个新行以保存历史记录。同样对于相同的 effective_date,您可以使用 effective_sequence 字段进行多个更改。员工数据如下所示:

EMPLOYEE_ID EFFECTIVE_DATE EFFECTIVE_SEQ ADRESS PHONE EMAIL
505 01/01/2020 1 MyHome 01 1113889 cparker@mail.com
505 15/12/2019 2 My Adress 02 1168206 cparker@mail.com
505 15/12/2019 1 1168206

我需要带上当前值的 select *,为最后一个值附加一个 select *。例如:

EMPLOYEE_ID_NOW EFFECTIVE_DATE_NOW EFFECTIVE_SEQ_NOW ADRESS_NOW PHONE_NOW EMAIL_NOW EMPLOYEE_ID_PREV EFFECTIVE_DATE_PREV EFFECTIVE_SEQ_PREV ADRESS_PREV PHONE_PREV EMAIL_PREV
505 01/01/2020 1 MyHome 01 1113889 cparker@mail.com 505 15/12/2019 2 My Adress 02 1168206 cparker@mail.com

Oracle 的版本是 11g

任何帮助将不胜感激。

谢谢

【问题讨论】:

  • employee_id_nowemployee_id_prev 没有意义。如果员工 id 发生变化,您如何按员工匹配行?

标签: sql oracle datetime pivot aggregate-functions


【解决方案1】:

如果你想要整个员工的前一行,你可以使用CTE,解析函数row_numberself join如下:

With cte as 
(Select t.*, 
        row_number() over (partition by employee_id  
                           order by effective_date desc, effecrive_seq desc) as rn
   From your_table t
)
Select t1.*, t2.*
  From cte t1 left join cte t2
    On t1.employee_id = t2.employee_id and t2.rn = 2
 Where t1.rn = 1

【讨论】:

  • 当然简单,喜欢它。非常感谢!
【解决方案2】:

您可以使用row_number() 和条件聚合:

select employee_id,
    max(effective_date) effective_date_now,
    max(case when rn = 1 then effective_seq end) as effective_seq_now,
    max(case when rn = 1 then address       end) as address_now,
    max(case when rn = 1 then phone         end) as phone_now,
    max(case when rn = 1 then email         end) as email_now,
    min(effective_date) effective_date_prev,
    max(case when rn = 2 then effective_seq end) as effective_seq_prev,
    max(case when rn = 2 then address       end) as address_prev,
    max(case when rn = 2 then phone         end) as phone_prev,
    max(case when rn = 2 then email         end) as email_prev
from (
    select e.*, 
        row_number() over(partition by employee_id order by effective_date desc, effective_seq desc) n
    from emp e
) e
where rn <= 2
group by employee_id

【讨论】:

    【解决方案3】:

    要恢复包含历史日期的表格的最后一个版本,您必须首先做两件事

    确定实体的主要实体

    这是您原始数据的主键,不考虑版本控制。

    我假设这是EMPLOYEE_ID

    识别历史表的主键和顺序

    在受过良好教育的数据库中,所有表都有一个主键,所以我假设列 EMPLOYEE_ID EFFECTIVE_DATE EFFECTIVE_SEQ 是这样的主键或至少是唯一的。

    我还假设历史版本的顺序(在一名员工内)是通过

    定义的

    ORDER BY EFFECTIVE_DATE, EFFECTIVE_SEQ

    如果这一点得到澄清,您将使用ROW_NUMBER 聚合函数获得最新版本,如下所示

    with emp as (
    select EMPLOYEE_ID, EFFECTIVE_DATE, EFFECTIVE_SEQ, ADRESS,
    row_number() over (partition by EMPLOYEE_ID /* partition by the entity PK */
                       order by EFFECTIVE_DATE desc, EFFECTIVE_SEQ desc) as rn /* use DESCendet history order */
    from tab)
    select * from emp
    where rn = 1
    

    如果您想添加一些previous 列,只需为每个必需的列添加一个LAG 函数,如下图所示ADDRESS

    请注意,这仅对历史属性有效 - 它对主键列无效。所以你不能像在你的示例数据中那样推断出EMPLOYEE_ID 的先前版本。

    lag(ADRESS,1,null) 基本上意味着您需要 first 以前的版本,如果不存在则提供 null - 因此,如果您需要更多历史记录或其他默认值,您可能会有所不同。 p>

    with emp as (
    select EMPLOYEE_ID, EFFECTIVE_DATE, EFFECTIVE_SEQ, ADRESS,
    lag(ADRESS,1,null) over (partition by EMPLOYEE_ID  
                       order by EFFECTIVE_DATE, EFFECTIVE_SEQ) as ADRESS_PREV, 
    row_number() over (partition by EMPLOYEE_ID   /* partition by the entity PK */
                       order by EFFECTIVE_DATE desc, EFFECTIVE_SEQ desc) as rn  /* use history order */
    from tab)
    select * from emp
    where rn = 1
    

    样本输出

    EMPLOYEE_ID EFFECTIVE_DATE      EFFECTIVE_SEQ ADRESS       ADRESS_PREV          RN
    ----------- ------------------- ------------- ------------ ------------ ----------
            505 01.01.2020 00:00:00             1 MyHome 01    My Adress 02          1
            506 15.12.2019 00:00:00             1 Sweet Home                         1
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-05-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多