Skip to Main Content
  • Questions
  • for each interval to put down a unique number

Breadcrumb

Question and Answer

Connor McDonald

Thanks for the question, Sergey.

Asked: October 07, 2015 - 2:01 pm UTC

Last updated: October 08, 2015 - 1:29 am UTC

Version: 11

Viewed 1000+ times

You Asked

Hi! Can you help me with this question:

for example we have a dataset:

DS DE RES_TYPE
12.10.2015 14:00:00 12.10.2015 14:20:00 3
12.10.2015 14:20:00 12.10.2015 14:40:00 3
12.10.2015 14:40:00 12.10.2015 15:00:00 3
12.10.2015 15:00:00 12.10.2015 15:20:00 0
12.10.2015 15:20:00 12.10.2015 15:40:00 0
12.10.2015 15:40:00 12.10.2015 16:00:00 0
12.10.2015 16:00:00 12.10.2015 16:20:00 1
12.10.2015 16:20:00 12.10.2015 16:40:00 1
12.10.2015 16:40:00 12.10.2015 17:00:00 0
12.10.2015 17:00:00 12.10.2015 17:20:00 0
12.10.2015 17:20:00 12.10.2015 17:40:00 0
12.10.2015 17:40:00 12.10.2015 18:00:00 0
12.10.2015 18:00:00 12.10.2015 18:20:00 0
12.10.2015 18:20:00 12.10.2015 18:40:00 0
12.10.2015 18:40:00 12.10.2015 19:00:00 0
12.10.2015 19:00:00 12.10.2015 19:20:00 3

What should a request to build that I have next result:

DS DE RES_TYPE FLAG
12.10.2015 14:00:00 12.10.2015 14:20:00 3 1
12.10.2015 14:20:00 12.10.2015 14:40:00 3 1
12.10.2015 14:40:00 12.10.2015 15:00:00 3 1
12.10.2015 15:00:00 12.10.2015 15:20:00 0 2
12.10.2015 15:20:00 12.10.2015 15:40:00 0 2
12.10.2015 15:40:00 12.10.2015 16:00:00 0 2
12.10.2015 16:00:00 12.10.2015 16:20:00 1 3
12.10.2015 16:20:00 12.10.2015 16:40:00 1 3
12.10.2015 16:40:00 12.10.2015 17:00:00 0 4
12.10.2015 17:00:00 12.10.2015 17:20:00 0 4
12.10.2015 17:20:00 12.10.2015 17:40:00 0 4
12.10.2015 17:40:00 12.10.2015 18:00:00 0 4
12.10.2015 18:00:00 12.10.2015 18:20:00 0 4
12.10.2015 18:20:00 12.10.2015 18:40:00 0 4
12.10.2015 18:40:00 12.10.2015 19:00:00 0 4
12.10.2015 19:00:00 12.10.2015 19:20:00 3 5

Thank you!


and Chris said...

Thanks for providing sample data and output. Please post the data in create table + insert form however - it makes it much easier to understand what's going on.

A brief description of the problem also helps! I'm guessing that you want to assign a new number every time the res_type changes, ordered by DS (= date start?)

Here's one way you can do this:

- First find whenver the res_type changes by comparing it to the value in the previous row (using lag). Assign value when this happens (e.g. with rownum)
- "Fill down" these assigned values for each res_type group
- Use dense_rank() to assign the flag rank you want

create table t ( 
  ds date, de date, res_type integer
);

insert into t values ('12.10.2015 14:00:00','12.10.2015 14:20:00',3);
insert into t values ('12.10.2015 14:20:00','12.10.2015 14:40:00',3);
insert into t values ('12.10.2015 14:40:00','12.10.2015 15:00:00',3);
insert into t values ('12.10.2015 15:00:00','12.10.2015 15:20:00',0);
insert into t values ('12.10.2015 15:20:00','12.10.2015 15:40:00',0);
insert into t values ('12.10.2015 15:40:00','12.10.2015 16:00:00',0);
insert into t values ('12.10.2015 16:00:00','12.10.2015 16:20:00',1);
insert into t values ('12.10.2015 16:20:00','12.10.2015 16:40:00',1);
insert into t values ('12.10.2015 16:40:00','12.10.2015 17:00:00',0);
insert into t values ('12.10.2015 17:00:00','12.10.2015 17:20:00',0);
insert into t values ('12.10.2015 17:20:00','12.10.2015 17:40:00',0);
insert into t values ('12.10.2015 17:40:00','12.10.2015 18:00:00',0);
insert into t values ('12.10.2015 18:00:00','12.10.2015 18:20:00',0);
insert into t values ('12.10.2015 18:20:00','12.10.2015 18:40:00',0);
insert into t values ('12.10.2015 18:40:00','12.10.2015 19:00:00',0);
insert into t values ('12.10.2015 19:00:00','12.10.2015 19:20:00',3);
commit;

select ds, de, res_type, 
       --assign the final flag
       dense_rank() over (order by mx) flag
from (
  select t.*, 
         -- fill down the chagne flags
         max(r) over (order by ds) mx
  from  (
    select t.*, 
           -- find the changes in res_type
           case 
             when nvl(lag(res_type) over (order by ds),-1) != res_type then rownum 
           end r
    from   t
  ) t
);

DS                  DE                    RES_TYPE       FLAG
------------------- ------------------- ---------- ----------
12/10/2015 14:00:00 12/10/2015 14:20:00          3          1
12/10/2015 14:20:00 12/10/2015 14:40:00          3          1
12/10/2015 14:40:00 12/10/2015 15:00:00          3          1
12/10/2015 15:00:00 12/10/2015 15:20:00          0          2
12/10/2015 15:20:00 12/10/2015 15:40:00          0          2
12/10/2015 15:40:00 12/10/2015 16:00:00          0          2
12/10/2015 16:00:00 12/10/2015 16:20:00          1          3
12/10/2015 16:20:00 12/10/2015 16:40:00          1          3
12/10/2015 16:40:00 12/10/2015 17:00:00          0          4
12/10/2015 17:00:00 12/10/2015 17:20:00          0          4
12/10/2015 17:20:00 12/10/2015 17:40:00          0          4
12/10/2015 17:40:00 12/10/2015 18:00:00          0          4
12/10/2015 18:00:00 12/10/2015 18:20:00          0          4
12/10/2015 18:20:00 12/10/2015 18:40:00          0          4
12/10/2015 18:40:00 12/10/2015 19:00:00          0          4
12/10/2015 19:00:00 12/10/2015 19:20:00          3          5

Rating

  (5 ratings)

Is this answer out of date? If it is, please let us know via a Comment

Comments

Thanks a lot!!!!

Sergey Ustinov, October 07, 2015 - 5:07 pm UTC

Thank you very,very,very,very,very much!!!!!! It's excellent!!! you are very help me!
Chris Saxon
October 07, 2015 - 7:06 pm UTC

Glad to be of help.

Two windows instead of one

Matthew McPeak, October 07, 2015 - 9:00 pm UTC

If the table is very large, you can do it in two steps instead of one by just counting the number of changes so far.

SELECT ds,
       ds,
       res_type,
       COUNT (change_indicator) OVER (PARTITION BY NULL ORDER BY ds) flag
FROM   (SELECT t.*,
               NULLIF (NVL (LAG (t.res_type) OVER (PARTITION BY NULL ORDER BY ds), -1), t.res_type) change_indicator
        FROM   t);

Such a common requirement

Stew Ashton, October 07, 2015 - 9:39 pm UTC

It's remarkable how often this same type of requirement comes up, often with respect to date ranges.

For future reference, please allow me to mention that 12c provides a new way of doing this:
select * from t
match_recognize(
  order by ds
  measures match_number() flag
  all rows per match
  pattern (a b*)
  define b as res_type = prev(res_type)
);

DS                        FLAG DE                    RES_TYPE
------------------- ---------- ------------------- ----------
12.10.2015 14:00:00          1 12.10.2015 14:20:00          3
12.10.2015 14:20:00          1 12.10.2015 14:40:00          3
12.10.2015 14:40:00          1 12.10.2015 15:00:00          3
12.10.2015 15:00:00          2 12.10.2015 15:20:00          0
12.10.2015 15:20:00          2 12.10.2015 15:40:00          0
12.10.2015 15:40:00          2 12.10.2015 16:00:00          0
12.10.2015 16:00:00          3 12.10.2015 16:20:00          1
12.10.2015 16:20:00          3 12.10.2015 16:40:00          1
12.10.2015 16:40:00          4 12.10.2015 17:00:00          0
12.10.2015 17:00:00          4 12.10.2015 17:20:00          0
12.10.2015 17:20:00          4 12.10.2015 17:40:00          0
12.10.2015 17:40:00          4 12.10.2015 18:00:00          0
12.10.2015 18:00:00          4 12.10.2015 18:20:00          0
12.10.2015 18:20:00          4 12.10.2015 18:40:00          0
12.10.2015 18:40:00          4 12.10.2015 19:00:00          0
12.10.2015 19:00:00          5 12.10.2015 19:20:00          3
If only someone that actually has 12c would ask this question!
Chris Saxon
October 08, 2015 - 1:29 am UTC

For anyone visiting this question, here's an important link for upgrading to 12c

https://blogs.oracle.com/UPGRADE/entry/new_version_of_the_big


The Model Boy !

Rajeshwaran, Jeyabal, October 08, 2015 - 1:47 pm UTC

rajesh@ORA10G>
rajesh@ORA10G> select *
  2  from t
  3  model
  4    dimension by ( row_number() over(order by ds) rn)
  5    measures(ds,de,res_type, 0 grp)
  6    rules
  7    ( grp[any] order by rn = case when cv(rn) = 1 then 1
  8                when cv(rn) > 1 and res_type[cv()] = res_type[cv()-1] then
  9                    grp[cv()-1] else grp[cv()-1]+1 end
 10    ) ;

        RN DS                  DE                    RES_TYPE        GRP
---------- ------------------- ------------------- ---------- ----------
         1 12.10.2015 14:00:00 12.10.2015 14:20:00          3          1
         2 12.10.2015 14:20:00 12.10.2015 14:40:00          3          1
         3 12.10.2015 14:40:00 12.10.2015 15:00:00          3          1
         4 12.10.2015 15:00:00 12.10.2015 15:20:00          0          2
         5 12.10.2015 15:20:00 12.10.2015 15:40:00          0          2
         6 12.10.2015 15:40:00 12.10.2015 16:00:00          0          2
         7 12.10.2015 16:00:00 12.10.2015 16:20:00          1          3
         8 12.10.2015 16:20:00 12.10.2015 16:40:00          1          3
         9 12.10.2015 16:40:00 12.10.2015 17:00:00          0          4
        10 12.10.2015 17:00:00 12.10.2015 17:20:00          0          4
        11 12.10.2015 17:20:00 12.10.2015 17:40:00          0          4
        12 12.10.2015 17:40:00 12.10.2015 18:00:00          0          4
        13 12.10.2015 18:00:00 12.10.2015 18:20:00          0          4
        14 12.10.2015 18:20:00 12.10.2015 18:40:00          0          4
        15 12.10.2015 18:40:00 12.10.2015 19:00:00          0          4
        16 12.10.2015 19:00:00 12.10.2015 19:20:00          3          5

16 rows selected.

rajesh@ORA10G>

With plans in place

Rajeshwaran, Jeyabal, October 08, 2015 - 1:53 pm UTC

rajesh@ORA10G> set autotrace traceonly explain
rajesh@ORA10G>
rajesh@ORA10G> select ds, de, res_type,
  2         --assign the final flag
  3         dense_rank() over (order by mx) flag
  4  from (
  5    select t.*,
  6           -- fill down the chagne flags
  7           max(r) over (order by ds) mx
  8    from  (
  9      select t.*,
 10             -- find the changes in res_type
 11             case
 12               when nvl(lag(res_type) over (order by ds),-1) != res_type then rownum
 13             end r
 14      from   t
 15    ) t
 16  );

Execution Plan
----------------------------------------------------------
Plan hash value: 1000669047

--------------------------------------------------------------------------------
| Id  | Operation               | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------
|   0 | SELECT STATEMENT        |      |    16 |   704 |     5  (40)| 00:00:01 |
|   1 |  WINDOW SORT            |      |    16 |   704 |     5  (40)| 00:00:01 |
|   2 |   VIEW                  |      |    16 |   704 |     4  (25)| 00:00:01 |
|   3 |    WINDOW BUFFER        |      |    16 |   704 |     4  (25)| 00:00:01 |
|   4 |     VIEW                |      |    16 |   704 |     4  (25)| 00:00:01 |
|   5 |      WINDOW SORT        |      |    16 |   288 |     4  (25)| 00:00:01 |
|   6 |       COUNT             |      |       |       |            |          |
|   7 |        TABLE ACCESS FULL| T    |    16 |   288 |     3   (0)| 00:00:01 |
--------------------------------------------------------------------------------

rajesh@ORA10G>
rajesh@ORA10G> select *
  2  from t
  3  model
  4    dimension by ( row_number() over(order by ds) rn)
  5    measures(ds,de,res_type, 0 grp)
  6    rules
  7    ( grp[any] order by rn = case when cv(rn) = 1 then 1
  8                when cv(rn) > 1 and res_type[cv()] = res_type[cv()-1] then
  9                    grp[cv()-1] else grp[cv()-1]+1 end
 10    );

Execution Plan
----------------------------------------------------------
Plan hash value: 852810556

----------------------------------------------------------------------------
| Id  | Operation           | Name | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------
|   0 | SELECT STATEMENT    |      |    16 |   288 |     4  (25)| 00:00:01 |
|   1 |  SQL MODEL ORDERED  |      |    16 |   288 |     4  (25)| 00:00:01 |
|   2 |   WINDOW SORT       |      |    16 |   288 |     4  (25)| 00:00:01 |
|   3 |    TABLE ACCESS FULL| T    |    16 |   288 |     3   (0)| 00:00:01 |
----------------------------------------------------------------------------

rajesh@ORA10G>
rajesh@ORA10G>
rajesh@ORA10G>

More to Explore

Analytics

Analytic SQL got you confused? Check out Connor McDonald's complete video course.