date | customer | orders | desired result |
---|---|---|---|
31-Mar | cus1 | 1 | 1 |
01-Apr | cus1 | 1 | 2 |
02-Apr | cus1 | 0 | 0 |
03-Apr | cus1 | 0 | 0 |
04-Apr | cus1 | 1 | 1 |
05-Apr | cus1 | 1 | 2 |
06-Apr | cus1 | 1 | 3 |
07-Apr | cus1 | 1 | 4 |
08-Apr | cus1 | 1 | 5 |
09-Apr | cus1 | 1 | 6 |
01-Apr | cus2 | 0 | 0 |
02-Apr | cus2 | 0 | 0 |
03-Apr | cus2 | 1 | 1 |
04-Apr | cus2 | 1 | 2 |
05-Apr | cus2 | 1 | 3 |
06-Apr | cus2 | 0 | 0 |
07-Apr | cus2 | 1 | 1 |
Here I have a table with dates , customers and their orders... i want a column to look like desired result in order to get my report functional. How can i do this using sql?
I have tried
row_number() over(partition by customer_id,desired_result order by work_date
)
but that doesnot work,
what it does is this - current results
date | customer | orders | desired result | current results |
---|---|---|---|---|
31-Mar | cus1 | 1 | 1 | 1 |
01-Apr | cus1 | 1 | 2 | 2 |
02-Apr | cus1 | 0 | 0 | 1 |
03-Apr | cus1 | 0 | 0 | 2 |
04-Apr | cus1 | 1 | 1 | 3 |
05-Apr | cus1 | 1 | 2 | 4 |
06-Apr | cus1 | 1 | 3 | 5 |
07-Apr | cus1 | 1 | 4 | 6 |
08-Apr | cus1 | 1 | 5 | 7 |
09-Apr | cus1 | 1 | 6 | 8 |
01-Apr | cus2 | 0 | 0 | 1 |
02-Apr | cus2 | 0 | 0 | 2 |
03-Apr | cus2 | 1 | 1 | 1 |
04-Apr | cus2 | 1 | 2 | 2 |
05-Apr | cus2 | 1 | 3 | 3 |
06-Apr | cus2 | 0 | 0 | 3 |
07-Apr | cus2 | 1 | 1 | 4 |
with data(dat, customer, orders, desired_result) as (
select to_date('31-03', 'DD-MM'), 'cus1', 1, 1 from dual union all
select to_date('01-04', 'DD-MM'), 'cus1', 1, 2 from dual union all
select to_date('02-04', 'DD-MM'), 'cus1', 0, 0 from dual union all
select to_date('03-04', 'DD-MM'), 'cus1', 0, 0 from dual union all
select to_date('04-04', 'DD-MM'), 'cus1', 1, 1 from dual union all
select to_date('05-04', 'DD-MM'), 'cus1', 1, 2 from dual union all
select to_date('06-04', 'DD-MM'), 'cus1', 1, 3 from dual union all
select to_date('07-04', 'DD-MM'), 'cus1', 1, 4 from dual union all
select to_date('08-04', 'DD-MM'), 'cus1', 1, 5 from dual union all
select to_date('09-04', 'DD-MM'), 'cus1', 1, 6 from dual union all
select to_date('01-04', 'DD-MM'), 'cus2', 0, 0 from dual union all
select to_date('02-04', 'DD-MM'), 'cus2', 0, 0 from dual union all
select to_date('03-04', 'DD-MM'), 'cus2', 1, 1 from dual union all
select to_date('04-04', 'DD-MM'), 'cus2', 1, 2 from dual union all
select to_date('05-04', 'DD-MM'), 'cus2', 1, 3 from dual union all
select to_date('06-04', 'DD-MM'), 'cus2', 0, 0 from dual union all
select to_date('07-04', 'DD-MM'), 'cus2', 1, 1 from dual -- union all
)
select d.dat, d.customer, d.orders,
case when orders <> 0 then row_number() over(partition by customer ||
'-' || decode(orders,0,0,1) || '-' || cn order by dat) else 0 end as rn
from (
select d.*,
sum(case when orders = 0 then 1 else 0 end) over(partition by customer order by dat) as cn
from data d
) d
order by customer, dat
;
31/03/24 cus1 1 1
01/04/24 cus1 1 2
02/04/24 cus1 0 0
03/04/24 cus1 0 0
04/04/24 cus1 1 1
05/04/24 cus1 1 2
06/04/24 cus1 1 3
07/04/24 cus1 1 4
08/04/24 cus1 1 5
09/04/24 cus1 1 6
01/04/24 cus2 0 0
02/04/24 cus2 0 0
03/04/24 cus2 1 1
04/04/24 cus2 1 2
05/04/24 cus2 1 3
06/04/24 cus2 0 0
07/04/24 cus2 1 1
Or with MATCH_RECOGNIZE:
SELECT dat,
customer,
orders,
CASE WHEN orders <> 0 THEN rn ELSE 0 END AS rn
FROM data
MATCH_RECOGNIZE(
PARTITION BY customer
ORDER BY dat
MEASURES
COUNT(orders) AS rn
ALL ROWS PER MATCH
PATTERN ( WITH_ORDER+ | WITHOUT_ORDERS )
DEFINE WITH_ORDER AS orders <> 0
);