Oracle 仅列出更改的记录

Posted

技术标签:

【中文标题】Oracle 仅列出更改的记录【英文标题】:Oracle list only records that changed 【发布时间】:2019-05-07 04:22:54 【问题描述】:

我有以下代码生成一个如图所示的表格:

with test (code, datum) as
      (select 600, date '2018-02-01' from dual union all
       select 600, date '2018-02-02' from dual union all
       select 0, date '2018-02-03' from dual union all
       select 0, date '2018-02-04' from dual union all
       select 0, date '2018-02-05' from dual union all
       select 600, date '2018-02-06' from dual union all
       select 600, date '2018-02-07' from dual union all
       select 0, date '2018-02-08' from dual union all
       select 0, date '2018-02-09' from dual
      )

    select * from test;

我尝试了以下方法,但没有返回我需要的内容。

    select * from (
    select test.*, min(datum) over (partition by code order by code) as min_date, 
    max(datum) over (partition by code order by code) as max_date  
    from test) where min_date = datum;

我想要实现的是仅列出“代码”列上发生更改的记录(发生更改的记录之前和之后)。

所以结果集应该是这样的:

02/FEB/18 00:00:00  600
03/FEB/18 00:00:00  0
05/FEB/18 00:00:00  0
06/FEB/18 00:00:00  600
07/FEB/18 00:00:00  600
08/FEB/18 00:00:00  0

我引用了这个问题,但它没有解决我遇到的相同问题。

question

感谢您的帮助。

更新:

这更接近我想要实现的目标。我可以列出列代码和更改不相同的所有行。但是,我还需要在这些值不同的地方列出记录。

with test (code, datum) as
  (select 600, date '2018-02-01' from dual union all
   select 600, date '2018-02-02' from dual union all
   select 0, date '2018-02-03' from dual union all
   select 0, date '2018-02-04' from dual union all
   select 0, date '2018-02-05' from dual union all
   select 600, date '2018-02-06' from dual union all
   select 600, date '2018-02-07' from dual union all
   select 0, date '2018-02-08' from dual union all
   select 0, date '2018-02-09' from dual
  )
  ,y1 as (
    select test.datum, test.code, lead(code) over (order by datum) as change
    from test
  )
select * from y1;

最终结果集应仅包含突出显示的行。

更新 2:

我想我可能做对了,仍然需要验证,但这似乎有效:

 with test (code, datum) as
      (select 600, date '2018-02-01' from dual union all
       select 600, date '2018-02-02' from dual union all
       select 0, date '2018-02-03' from dual union all
       select 0, date '2018-02-04' from dual union all
       select 0, date '2018-02-05' from dual union all
       select 600, date '2018-02-06' from dual union all
       select 600, date '2018-02-07' from dual union all
       select 0, date '2018-02-08' from dual union all
       select 0, date '2018-02-09' from dual
      )
      ,y1 as (
        select test.datum, test.code, lag(nvl(code,code)) over (order by datum) as after, lead(nvl(code,code)) over (order by datum) as before
        from test
      )
      select * from y1 where code != before or code != after;

【问题讨论】:

What I would like to achieve is list only the records where a change occurs on the 'code' column -- 识别列发生变化的机制是什么? 本质上,我们使用的是按升序排列的基准列。因此它将从第一行开始,当代码发生更改时,它将打印更改之前的行以及更改之后的行。简而言之,随着时间(数据)的移动显示代码的旧值和新值。 【参考方案1】:

不确定这是否会帮助我看不到任何相关性来整理您问题中的预期输出。

with test (code, datum) as
  (select 600, date '2018-02-01' from dual union all
   select 600, date '2018-02-02' from dual union all
   select 0, date '2018-02-03' from dual union all
   select 0, date '2018-02-04' from dual union all
   select 0, date '2018-02-05' from dual union all
   select 600, date '2018-02-06' from dual union all
   select 600, date '2018-02-07' from dual union all
   select 0, date '2018-02-08' from dual union all
   select 0, date '2018-02-09' from dual
  )
  ,y1 as (
    select test.datum, test.code, lead(code) over (order by datum) as change
    from test
    UNION 
    select test.datum, test.code, lag(code) over (order by datum) as change
    from test

  )
select * from y1 
where change = 600;

【讨论】:

感谢您提供的代码,它给了我一个想法,我想我得到了我想要的。我已经发布了更新版本。 XING,答案是错误的,你应该删除或编辑它。 @akk0rd87 感谢您耐心阅读问题,然后将我的答案评估为不正确。但是,如果您阅读了我的 cmets 和 OP cmets,我也会有 appreciated您。我已经写了我的答案接近用户的预期,他也提到它有帮助。不确定您是否有一些可以帮助用户的答案,然后请发布。 SO 不仅仅是一个提供正确答案的社区,如果您的指示可以帮助某人得出解决问题的结论,这一点也很重要。【参考方案2】:

以下脚本产生了预期的结果集:

with test (code, datum) as
      (select 600, date '2018-02-01' from dual union all
       select 600, date '2018-02-02' from dual union all
       select 0, date '2018-02-03' from dual union all
       select 0, date '2018-02-04' from dual union all
       select 0, date '2018-02-05' from dual union all
       select 600, date '2018-02-06' from dual union all
       select 600, date '2018-02-07' from dual union all
       select 0, date '2018-02-08' from dual union all
       select 0, date '2018-02-09' from dual
      )
      ,y1 as (
        select test.datum, test.code, lag(nvl(code,code)) over (order by datum) as after, lead(nvl(code,code)) over (order by datum) as before
        from test
      )
      select * from y1 where code != before or code != after;

【讨论】:

以上是关于Oracle 仅列出更改的记录的主要内容,如果未能解决你的问题,请参考以下文章

从包含 155K 记录的表中获取仅在组合框中列出的 65K 记录

在oracle中仅选择且仅选择特定记录[关闭]

Laravel 5.3更新记录。仅更新已更改的记录并保留未更改的记录

ORACLE 如果任何字段更改,则添加新记录

使用 POJO 仅更新 JOOQ 记录中更改的字段

如何更改 CloudKit 仪表板左栏中每条记录的显示内容?