Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Oracle get row where column value changed

Say I have a table, something like

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

There are other fields, but I made it simple. So I create a query where i have the date in descending order. I was to return the row where there was a change in CCTR. So in this case it would return ID 4. Basically i want to find the previous value of CCTR before it changed, in this case from 2B to 2C.

How do I do this? Ive tried to google it, but can't seem to find the right method.

like image 351
dk96m Avatar asked Dec 02 '25 22:12

dk96m


2 Answers

You can use the LAG() window function to peek at the previous row and compare it. If your data is:

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');

Then the query would be:

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
);

Result:

ID       CCTR        DATE1    
-------  ----------  -------------------
4        2B          2017-03-02 00:00:00  
like image 71
The Impaler Avatar answered Dec 04 '25 17:12

The Impaler


You may use first_value analytic function to detect the changes in CCTR column :

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

like image 20
Barbaros Özhan Avatar answered Dec 04 '25 16:12

Barbaros Özhan



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!