【问题标题】:Oracle get row where column value changedOracle获取列值更改的行
【发布时间】:2019-02-18 06:00:28
【问题描述】:

假设我有一张桌子,比如

ID     CCTR    DATE
-----  ------  ----------
1      2C      8/1/2018
2      2C      7/2/2018
3      2C      5/4/2017
4      2B      3/2/2017
5      2B      1/1/2017
6      UC      11/23/2016

还有其他字段,但我把它简单化了。所以我创建了一个查询,其中我的日期按降序排列。我要返回 CCTR 发生变化的行。所以在这种情况下它会返回 ID 4。基本上我想找到 CCTR 在它改变之前的先前值,在这种情况下从 2B 到 2C。

我该怎么做?我已经尝试谷歌它,但似乎找不到正确的方法。

【问题讨论】:

  • 使用LAG()窗口函数。

标签: sql oracle analytic-functions


【解决方案1】:

您可以使用LAG() 窗口函数查看上一行并进行比较。如果您的数据是:

create table t2 (
  id number(6),
  cctr varchar2(10),
  date1 date
);

insert into t2 (id, cctr, date1) values (1, '2C', date '2018-08-01');
insert into t2 (id, cctr, date1) values (2, '2C', date '2018-07-02');
insert into t2 (id, cctr, date1) values (3, '2C', date '2017-05-04');
insert into t2 (id, cctr, date1) values (4, '2B', date '2017-03-02');
insert into t2 (id, cctr, date1) values (5, '2B', date '2017-01-01');
insert into t2 (id, cctr, date1) values (6, 'UC', date '2016-11-23');

那么查询将是:

select * from t2 where date1 = (
  select max(date1)
    from (
    select 
      id, date1, cctr, lag(cctr) over(order by date1 desc) as prev
      from t2
    ) x  
    where prev is not null and cctr <> prev
);

结果:

ID       CCTR        DATE1    
-------  ----------  -------------------
4        2B          2017-03-02 00:00:00  

【讨论】:

  • 我认为这也应该报告 UC 行。
  • 确实如此,但我使用MAX() 将其过滤掉了。他只想要最后一个,对吧?
  • 这行得通。如果我想在它改变后获得第一行怎么办?所以在这种情况下 id 3
  • 好的,所以如果我添加employeeid,我如何获得相同的结果,但对于每个员工。因此,符合上述标准的每个员工都会有一行
  • 感谢这个例子帮助我更好地理解了这个功能,并编写了一个查询来查找员工最近更换主管的日期。
【解决方案2】:

您可以使用first_value解析函数来检测CCTR栏的变化:

select fv as value, cctr
  from 
(
  with t(ID,CCTR) as
  (
   select 1,'2C' from dual union all
   select 2,'2C' from dual union all
   select 3,'2C' from dual union all
   select 4,'2B' from dual union all
   select 5,'2B' from dual union all
   select 6,'UC' from dual
  ) 
  select id, cctr, first_value(id) over (partition by cctr order by id ) fv
    from t
  order by id
)  
where id = fv;

VALUE  CCTR
-----  ----
  1     2C
  4     2B
  6     UC

Rextester Demo

【讨论】:

  • 我会使用这种方法作为标准技术。
  • 是的,但这会返回所有更改,我只想要最后一个更改,在本例中为 ID 4
  • 让我稍微改变一下。让我们添加employeeid 字段。我如何获得符合每个员工标准的行
猜你喜欢
  • 1970-01-01
  • 2015-03-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-21
  • 1970-01-01
  • 2023-02-17
相关资源
最近更新 更多