I have a oracle query which is executed once a month to get the order details processed. This query is taking a painfully lot of time to execute. ( More than thirty mins ). Therefore I am trying to optimize this. I have a decent knowledge in Oracle and I will explain what I have tried so far. Still, it takes around 20 minutes to complete. This is the query. Oracle version is 11g.
SELECT store_typ, store_no, COUNT(order_no) FROM
(
SELECT DISTINCT(order_no), store.store_no, store.store_typ FROM
(
SELECT trx.order_no,trx.ADDED_DATE, odr.prod_typ, odr.store_no FROM daily_trx trx
LEFT OUTER JOIN
(
SELECT odr.order_no,odr.prod_typ,prod.store_no FROM order_main odr
LEFT OUTER JOIN ORDR_PROD_TYP prod
on odr.prod_typ = prod.prod_typ
) odr
ON trx.order_no= odr.order_no
) daily_orders ,
(SELECT store_no,store_typ FROM main_stores ) store
WHERE 1=1
and daily_orders.order_no !='NA'
and store.store_no = daily_orders.store_no
AND to_timestamp(to_char(daily_orders.ADDED_DATE,'DD-MM-YYYY HH24:MI:SS'),'DD-MM-YYYY HH24:MI:SS') >= to_date('01-05-2020 00:00:00','DD-MM-YYYY HH24:MI:SS')
AND to_timestamp(to_char(daily_orders.ADDED_DATE,'DD-MM-YYYY HH24:MI:SS'),'DD-MM-YYYY HH24:MI:SS') <= to_date('31-05-2020 23:59:59','DD-MM-YYYY HH24:MI:SS')
)
GROUP BY store_typ, store_no
Background
order_main - This table has over 4 million records
I introduced index for order_no column which reduced time to execute.
My questions are as follows.
1) Will it help if I move date validation inside the inner query like this ?
SELECT store_typ, store_no, COUNT(order_no) FROM
(
SELECT DISTINCT(order_no), store.store_no, store.store_typ FROM
(
SELECT trx.order_no,trx.ADDED_DATE, odr.prod_typ, odr.store_no FROM daily_trx trx
LEFT OUTER JOIN
(
SELECT odr.order_no,odr.prod_typ,prod.store_no FROM order_main odr
LEFT OUTER JOIN ORDR_PROD_TYP prod
on odr.prod_typ = prod.prod_typ
) odr
ON trx.order_no= odr.order_no
WHERE to_timestamp(to_char(daily_orders.ADDED_DATE,'DD-MM-YYYY HH24:MI:SS'),'DD-MM-YYYY HH24:MI:SS') >= to_date('01-05-2020 00:00:00','DD-MM-YYYY HH24:MI:SS')
AND to_timestamp(to_char(daily_orders.ADDED_DATE,'DD-MM-YYYY HH24:MI:SS'),'DD-MM-YYYY HH24:MI:SS') <= to_date('31-05-2020 23:59:59','DD-MM-YYYY HH24:MI:SS')
) daily_orders ,
(SELECT store_no,store_typ FROM main_stores ) store
WHERE 1=1
and daily_orders.order_no !='NA'
and store.store_no = daily_orders.store_no
--AND to_timestamp(to_char(daily_orders.ADDED_DATE,'DD-MM-YYYY HH24:MI:SS'),'DD-MM-YYYY HH24:MI:SS') >= to_date('01-05-2020 00:00:00','DD-MM-YYYY HH24:MI:SS')
--AND to_timestamp(to_char(daily_orders.ADDED_DATE,'DD-MM-YYYY HH24:MI:SS'),'DD-MM-YYYY HH24:MI:SS') <= to_date('31-05-2020 23:59:59','DD-MM-YYYY HH24:MI:SS')
)
GROUP BY store_typ, store_no
2) Could someone please suggest any other improvements that can be done to this query?
3) Additional indexing would help in any other tables / columns ? Only daily_trx and order_main tables are the tables that contains huge amount of data.
Some generall suggestions
Do not combine ANSI and Oracle Join Syntax in one Query
Do not use outer join if inner join can be used
Your inner subqueries use outer joins, but the final join to main_stores is an inner join
eliminating all rows with store_no is null - you may use inner joins with the same result.
Filter rows early
A suboptimal practice is to first join in a subquery and than filter relevant row with where conditions
Use simple predicated
If you want to constraint a DATE column do it this way
trx.ADDED_DATE >= to_date('01-05-2020 00:00:00','DD-MM-YYYY HH24:MI:SS')
Use count distinct if appropriate
The select DISTINCTquery in the third line cam be eliminated if you use COUNT(DISTINCT order_no)
Applying all the above point I come to the following query
select
store.store_no, store.store_typ, count(DISTINCT trx.order_no) order_no_cnt
from daily_trx trx
join order_main odr on trx.order_no = odr.order_no
join ordr_prod_typ prod on odr.prod_typ = prod.prod_typ
join main_stores store on store.store_no = prod.store_no
where trx.ADDED_DATE >= date'2020-05-01' and
trx.ADDED_DATE < date'2020-06-01' and
trx.order_no !='NA'
group by store.store_no, store.store_typ
Performance Considereations
You process a month of data, so there will be probably a large number of transaction (say 100K+). In this case the best approach is to full scan the two large tables and perform HASH JOINs.
You can expect this execution plan
----------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
----------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 199K| 5850K| | 592 (2)| 00:00:08 |
|* 1 | HASH JOIN | | 199K| 5850K| | 592 (2)| 00:00:08 |
| 2 | TABLE ACCESS FULL | MAIN_STORES | 26 | 104 | | 3 (0)| 00:00:01 |
|* 3 | HASH JOIN | | 199K| 5070K| | 588 (2)| 00:00:08 |
| 4 | TABLE ACCESS FULL | ORDR_PROD_TYP | 26 | 104 | | 3 (0)| 00:00:01 |
|* 5 | HASH JOIN | | 199K| 4290K| 1960K| 584 (1)| 00:00:08 |
|* 6 | TABLE ACCESS FULL| ORDER_MAIN | 100K| 782K| | 69 (2)| 00:00:01 |
|* 7 | TABLE ACCESS FULL| DAILY_TRX | 200K| 2734K| | 172 (2)| 00:00:03 |
----------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("STORE"."STORE_NO"="PROD"."STORE_NO")
3 - access("ODR"."PROD_TYP"="PROD"."PROD_TYP")
5 - access("TRX"."ORDER_NO"="ODR"."ORDER_NO")
6 - filter("ODR"."ORDER_NO"<>'NA')
7 - filter("TRX"."ADDED_DATE"<TO_DATE(' 2020-06-01 00:00:00', 'syyyy-mm-dd
hh24:mi:ss') AND "TRX"."ORDER_NO"<>'NA' AND "TRX"."ADDED_DATE">=TO_DATE(' 2020-05-01
00:00:00', 'syyyy-mm-dd hh24:mi:ss'))
If you have a partition option available you will massively profit by defining a monthly partitioning schema (alternative a daily partitioning) on the two tables DAILY_TRX and ORDER_MAIN.
If the above assumption is not correct and you have very few transactions in the selected time interval (say below 1K) - you will go better using the index access and NESTED LOOPS joins.
You will need this set of indices
create index daily_trx_date on daily_trx(ADDED_DATE);
create unique index order_main_idx on order_main (order_no);
create unique index ORDR_PROD_TYP_idx1 on ORDR_PROD_TYP(prod_typ);
create unique index main_stores_idx1 on main_stores(store_no);
The expected plan is as follows
---------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 92 | 2760 | 80 (4)| 00:00:01 |
|* 1 | HASH JOIN | | 92 | 2760 | 80 (4)| 00:00:01 |
|* 2 | TABLE ACCESS BY INDEX ROWID | DAILY_TRX | 92 | 1288 | 4 (0)| 00:00:01 |
|* 3 | INDEX RANGE SCAN | DAILY_TRX_DATE | 92 | | 3 (0)| 00:00:01 |
|* 4 | HASH JOIN | | 100K| 1564K| 75 (3)| 00:00:01 |
| 5 | MERGE JOIN | | 26 | 208 | 6 (17)| 00:00:01 |
| 6 | TABLE ACCESS BY INDEX ROWID| MAIN_STORES | 26 | 104 | 2 (0)| 00:00:01 |
| 7 | INDEX FULL SCAN | MAIN_STORES_IDX1 | 26 | | 1 (0)| 00:00:01 |
|* 8 | SORT JOIN | | 26 | 104 | 4 (25)| 00:00:01 |
| 9 | TABLE ACCESS FULL | ORDR_PROD_TYP | 26 | 104 | 3 (0)| 00:00:01 |
|* 10 | TABLE ACCESS FULL | ORDER_MAIN | 100K| 782K| 69 (2)| 00:00:01 |
---------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("TRX"."ORDER_NO"="ODR"."ORDER_NO")
2 - filter("TRX"."ORDER_NO"<>'NA')
3 - access("TRX"."ADDED_DATE">=TO_DATE(' 2020-06-01 00:00:00', 'syyyy-mm-dd
hh24:mi:ss') AND "TRX"."ADDED_DATE"<TO_DATE(' 2020-07-01 00:00:00', 'syyyy-mm-dd
hh24:mi:ss'))
4 - access("ODR"."PROD_TYP"="PROD"."PROD_TYP")
8 - access("STORE"."STORE_NO"="PROD"."STORE_NO")
filter("STORE"."STORE_NO"="PROD"."STORE_NO")
10 - filter("ODR"."ORDER_NO"<>'NA')
Check here how to get the execution plan of your query
I have below input data in table
+-----------+-------+-----------------+-----------------+------------------+-------------------+
device_count| dmc_id| firmware_version| charging_group_id|image_prerequisite| count_within_dmcid|
+-----------+-------+-----------------+-----------------+------------------+-------------------+
| 5 | 3345 |SU.B |0000000000000000 |SU.A | 93 |
| 6 | 3345 |SU.C |0000000000000000 |SU.B | 93 |
| 8 | 3345 |SU.D |0000000000000000 |SU.C | 93 |
| 8 | 3345 |SU.E |0000000000000000 |SU.C | 93 |
| 20 | 3345 |SU.F |0000000000000000 |SU.D | 93 |
| 20 | 3345 |SU.F |0000000000000000 |SU.E | 93 |
| 10 | 3345 |SU.G |0000000000000000 |SU.F | 93 |
| 11 | 3345 |SU.H |0000000000000000 |SU.F | 93 |
| 20 | 3345 |SU.I |0000000000000000 |SU.G | 93 |
| 20 | 3345 |SU.I |0000000000000000 |SU.H | 93 |
| 5 | 3345 |SU.A |0000000000000000 |null | 93 |
| 40 | 408 |RT2 |0000000000000000 |RT1 | 24028 |
| 24 | 408 |RT3 |0000000000000000 |RT2 | 24028 |
| 18 | 408 |RT4 |0000000000000000 |RT3 | 24028 |
| 2109 | 408 |RT1 |0000000000000000 |null | 24028 |
| 1 | 1422 |RT1 |0000000000000000 |null | 7 |
| 1 | 1422 |RT2 |0000000000000000 |RT1 | 7 |
| 1 | 408 |RT1 |HFOTA-0000000041 |null | 1 |
| 1 | 408 |RT1 |HFOTA-0000000334 |null | 2 |
| 1 | 408 |RT1 |HFOTA-0000000359 |null | 1 |
| 1 | 408 |RT1 |HFOTA-0000000441 |null | 1 |
| 1 | 408 |RT1 |HFOTA-0000001885 |null | 2 |
| 4 | 408 |SVP01 |0000000000000000 |null | 24028 |
| 11 | 408 |Sanity01 |0000000000000000 |null | 24028 |
| 1 | 408 |Sanity1 |0000000000000000 |null | 24028 |
| 6 | 408 |TB_HT01 |0000000000000000 |null | 24028 |
| 1 | 408 |TEST_1 |0000000000000000 |null | 24028 |
| 5 | 408 |TK_ST001 |0000000000000000 |null | 24028 |
| 2 | 3345 |FW.D |0000000000000000 |FW.C | 24028 |
| 8 | 3345 |FW.E |0000000000000000 |FW.D | 24028 |
| 4 | 3345 |FW.F |0000000000000000 |FW.E | 24028 |
+-----------+-------+-----------------+-----------------+------------------+-------------------+
I am using below query to create chain of firmware_version and finding cumulative count.
WITH t1 AS
(SELECT device_count,
dmc_id,
CASE
WHEN COUNT(image_prerequisite) OVER (PARTITION BY dmc_id, charging_group_id, image_prerequisite) > 1
THEN
MIN(firmware_version)
--WITHIN GROUP (ORDER BY firmware_version)
OVER (PARTITION BY dmc_id, charging_group_id, image_prerequisite) || '+N'
ELSE firmware_version
END firmware_version,
charging_group_id,
image_prerequisite,
count_within_dmcid
FROM dm_temp_summing_dvc_by_fw
),
t2 AS
(SELECT SUM(device_count) device_count,
dmc_id,
firmware_version,
charging_group_id,
image_prerequisite,
count_within_dmcid
FROM t1
GROUP BY dmc_id,
firmware_version,
charging_group_id,
image_prerequisite,
count_within_dmcid
),
t3 AS
(SELECT t.*,
LEVEL lev,
sys_connect_by_path(firmware_version, '/') AS chain,
connect_by_root(firmware_version) root_fw,
row_number() OVER (PARTITION BY dmc_id, charging_group_id, firmware_version, connect_by_root(firmware_version) ORDER BY LEVEL DESC, sys_connect_by_path(firmware_version, '/')) rn
FROM t2 t
START WITH image_prerequisite IS NULL
CONNECT BY nocycle PRIOR regexp_substr(firmware_version, '[^+]*') = image_prerequisite
AND PRIOR dmc_id = dmc_id
AND PRIOR charging_group_id = charging_group_id
)
SELECT chain,
root_fw,
firmware_version AS fw,
device_count AS cnt,
dmc_id,
charging_group_id,
count_within_dmcid,
SUM(device_count) over(PARTITION BY dmc_id, charging_group_id, root_fw ORDER BY lev DESC) AS cumm,
lev,
rn
FROM t3
ORDER BY dmc_id,
charging_group_id,
lev DESC;
Results Query is returning: It is not returning the chain for firmware_versions FW.D, FW.E, FW.F because we are using START WITH image_prerequisite IS NULL.
Please suggest a way we can address the chain of firmware which does not have the starting point (Image Prerequisite) as NULL.
CHAIN ROOT_FW FW CNT DMC_ID CG_ID LEV COUNT_WITHIN_DMCID RN CUMM
--------------------------------------------- ---------- --------------- ---------- ---------- ---------------- ---------- ------------------ ---------- ----------
/RT1/RT2/RT3/RT4 RT1 RT4 18 408 0000000000000000 4 24028 1 18
/RT1/RT2/RT3 RT1 RT3 24 408 0000000000000000 3 24028 1 42
/RT1/RT2 RT1 RT2 40 408 0000000000000000 2 24028 1 82
/SVP01 SVP01 SVP01 4 408 0000000000000000 1 24028 1 4
/RT1 RT1 RT1 2109 408 0000000000000000 1 24028 1 2191
/Sanity01 Sanity01 Sanity01 11 408 0000000000000000 1 24028 1 11
/Sanity1 Sanity1 Sanity1 1 408 0000000000000000 1 24028 1 1
/TB_HT01 TB_HT01 TB_HT01 6 408 0000000000000000 1 24028 1 6
/TEST_1 TEST_1 TEST_1 1 408 0000000000000000 1 24028 1 1
/TK_ST001 TK_ST001 TK_ST001 5 408 0000000000000000 1 24028 1 5
/RT1 RT1 RT1 1 408 HFOTA-0000000041 1 1 1 1
/RT1 RT1 RT1 1 408 HFOTA-0000000334 1 2 1 1
/RT1 RT1 RT1 1 408 HFOTA-0000000359 1 1 1 1
/RT1 RT1 RT1 1 408 HFOTA-0000000441 1 1 1 1
/RT1 RT1 RT1 1 408 HFOTA-0000001885 1 2 1 1
/RT1/RT2 RT1 RT2 1 1422 0000000000000000 2 7 1 1
/RT1 RT1 RT1 1 1422 0000000000000000 1 7 1 2
/SU.A/SU.B/SU.C/SU.D+N/SU.F/SU.G+N/SU.I SU.A SU.I 20 3345 0000000000000000 7 93 1 20
/SU.A/SU.B/SU.C/SU.D+N/SU.F/SU.G+N SU.A SU.G+N 21 3345 0000000000000000 6 93 1 41
/SU.A/SU.B/SU.C/SU.D+N/SU.F SU.A SU.F 20 3345 0000000000000000 5 93 1 61
/SU.A/SU.B/SU.C/SU.D+N SU.A SU.D+N 16 3345 0000000000000000 4 93 1 77
/SU.A/SU.B/SU.C SU.A SU.C 6 3345 0000000000000000 3 93 1 83
/SU.A/SU.B SU.A SU.B 5 3345 0000000000000000 2 93 1 88
/SU.A SU.A SU.A 5 3345 0000000000000000 1 93 1 93
Expected output:
CHAIN ROOT_FW FW CNT DMC_ID CG_ID LEV COUNT_WITHIN_DMCID RN CUMM
--------------------------------------------- ---------- --------------- ---------- ---------- ---------------- ---------- ------------------ ---------- ----------
/RT1/RT2/RT3/RT4 RT1 RT4 18 408 0000000000000000 4 24028 1 18
/RT1/RT2/RT3 RT1 RT3 24 408 0000000000000000 3 24028 1 42
/RT1/RT2 RT1 RT2 40 408 0000000000000000 2 24028 1 82
/SVP01 SVP01 SVP01 4 408 0000000000000000 1 24028 1 4
/RT1 RT1 RT1 2109 408 0000000000000000 1 24028 1 2191
/Sanity01 Sanity01 Sanity01 11 408 0000000000000000 1 24028 1 11
/Sanity1 Sanity1 Sanity1 1 408 0000000000000000 1 24028 1 1
/TB_HT01 TB_HT01 TB_HT01 6 408 0000000000000000 1 24028 1 6
/TEST_1 TEST_1 TEST_1 1 408 0000000000000000 1 24028 1 1
/TK_ST001 TK_ST001 TK_ST001 5 408 0000000000000000 1 24028 1 5
/RT1 RT1 RT1 1 408 HFOTA-0000000041 1 1 1 1
/RT1 RT1 RT1 1 408 HFOTA-0000000334 1 2 1 1
/RT1 RT1 RT1 1 408 HFOTA-0000000359 1 1 1 1
/RT1 RT1 RT1 1 408 HFOTA-0000000441 1 1 1 1
/RT1 RT1 RT1 1 408 HFOTA-0000001885 1 2 1 1
/RT1/RT2 RT1 RT2 1 1422 0000000000000000 2 7 1 1
/RT1 RT1 RT1 1 1422 0000000000000000 1 7 1 2
/SU.A/SU.B/SU.C/SU.D+N/SU.F/SU.G+N/SU.I SU.A SU.I 20 3345 0000000000000000 7 93 1 20
/SU.A/SU.B/SU.C/SU.D+N/SU.F/SU.G+N SU.A SU.G+N 21 3345 0000000000000000 6 93 1 41
/SU.A/SU.B/SU.C/SU.D+N/SU.F SU.A SU.F 20 3345 0000000000000000 5 93 1 61
/SU.A/SU.B/SU.C/SU.D+N SU.A SU.D+N 16 3345 0000000000000000 4 93 1 77
/SU.A/SU.B/SU.C SU.A SU.C 6 3345 0000000000000000 3 93 1 83
/SU.A/SU.B SU.A SU.B 5 3345 0000000000000000 2 93 1 88
/SU.A SU.A SU.A 5 3345 0000000000000000 1 93 1 93
/FW.D/FW.E/FW.F FW.D FW.F 4 3345 0000000000000000 3 93 1 4
/FW.D/FW.E FW.D FW.E 8 3345 0000000000000000 2 93 1 12
/FW.D FW.D FW.D 2 3345 0000000000000000 1 93 1 14
As I wrote in the comment, if you modify the START WITH clause in this way:
START WITH image_prerequisite IS NULL
OR image_prerequisite NOT IN (
SELECT firmware_version FROM dm_temp_summing_dvc_by_fw
)
then FWD will be included as a beginning of the chain.
This query: http://sqlfiddle.com/#!4/e4e13/3
gives the following results:
WITH t1 AS
(SELECT device_count,
dmc_id,
CASE
WHEN COUNT(image_prerequisite) OVER (PARTITION BY dmc_id, charging_group_id, image_prerequisite) > 1
THEN
MIN(firmware_version)
--WITHIN GROUP (ORDER BY firmware_version)
OVER (PARTITION BY dmc_id, charging_group_id, image_prerequisite) || '+N'
ELSE firmware_version
END firmware_version,
charging_group_id,
image_prerequisite,
count_within_dmcid
FROM dm_temp_summing_dvc_by_fw
),
t2 AS
(SELECT SUM(device_count) device_count,
dmc_id,
firmware_version,
charging_group_id,
image_prerequisite,
count_within_dmcid
FROM t1
GROUP BY dmc_id,
firmware_version,
charging_group_id,
image_prerequisite,
count_within_dmcid
),
t3 AS
(SELECT t.*,
LEVEL lev,
sys_connect_by_path(firmware_version, '/') AS chain,
connect_by_root(firmware_version) root_fw,
row_number() OVER (PARTITION BY dmc_id, charging_group_id, firmware_version, connect_by_root(firmware_version) ORDER BY LEVEL DESC, sys_connect_by_path(firmware_version, '/')) rn
FROM t2 t
START WITH image_prerequisite IS NULL
OR image_prerequisite NOT IN (
SELECT firmware_version FROM dm_temp_summing_dvc_by_fw
)
CONNECT BY nocycle PRIOR regexp_substr(firmware_version, '[^+]*') = image_prerequisite
AND PRIOR dmc_id = dmc_id
AND PRIOR charging_group_id = charging_group_id
)
SELECT chain,
root_fw,
firmware_version AS fw,
device_count AS cnt,
dmc_id,
charging_group_id,
count_within_dmcid,
SUM(device_count) over(PARTITION BY dmc_id, charging_group_id, root_fw ORDER BY lev DESC) AS cumm,
lev,
rn
FROM t3
ORDER BY 1;
| CHAIN | ROOT_FW | FW | CNT | DMC_ID | CHARGING_GROUP_ID | COUNT_WITHIN_DMCID | CUMM | LEV | RN |
|-----------------------------------------|----------|----------|------|--------|-------------------|--------------------|------|-----|----|
| /FW.D | FW.D | FW.D | 2 | 3345 | 0000000000000000 | 24028 | 14 | 1 | 1 |
| /FW.D/FW.E | FW.D | FW.E | 8 | 3345 | 0000000000000000 | 24028 | 12 | 2 | 1 |
| /FW.D/FW.E/FW.F | FW.D | FW.F | 4 | 3345 | 0000000000000000 | 24028 | 4 | 3 | 1 |
| /RT1 | RT1 | RT1 | 2109 | 408 | 0000000000000000 | 24028 | 2191 | 1 | 1 |
| /RT1 | RT1 | RT1 | 1 | 1422 | 0000000000000000 | 7 | 2 | 1 | 1 |
| /RT1 | RT1 | RT1 | 1 | 408 | HFOTA-0000000041 | 1 | 1 | 1 | 1 |
| /RT1 | RT1 | RT1 | 1 | 408 | HFOTA-0000000334 | 2 | 1 | 1 | 1 |
| /RT1 | RT1 | RT1 | 1 | 408 | HFOTA-0000001885 | 2 | 1 | 1 | 1 |
| /RT1 | RT1 | RT1 | 1 | 408 | HFOTA-0000000441 | 1 | 1 | 1 | 1 |
| /RT1 | RT1 | RT1 | 1 | 408 | HFOTA-0000000359 | 1 | 1 | 1 | 1 |
| /RT1/RT2 | RT1 | RT2 | 1 | 1422 | 0000000000000000 | 7 | 1 | 2 | 1 |
| /RT1/RT2 | RT1 | RT2 | 40 | 408 | 0000000000000000 | 24028 | 82 | 2 | 1 |
| /RT1/RT2/RT3 | RT1 | RT3 | 24 | 408 | 0000000000000000 | 24028 | 42 | 3 | 1 |
| /RT1/RT2/RT3/RT4 | RT1 | RT4 | 18 | 408 | 0000000000000000 | 24028 | 18 | 4 | 1 |
| /SU.A | SU.A | SU.A | 5 | 3345 | 0000000000000000 | 93 | 93 | 1 | 1 |
| /SU.A/SU.B | SU.A | SU.B | 5 | 3345 | 0000000000000000 | 93 | 88 | 2 | 1 |
| /SU.A/SU.B/SU.C | SU.A | SU.C | 6 | 3345 | 0000000000000000 | 93 | 83 | 3 | 1 |
| /SU.A/SU.B/SU.C/SU.D+N | SU.A | SU.D+N | 16 | 3345 | 0000000000000000 | 93 | 77 | 4 | 1 |
| /SU.A/SU.B/SU.C/SU.D+N/SU.F | SU.A | SU.F | 20 | 3345 | 0000000000000000 | 93 | 61 | 5 | 1 |
| /SU.A/SU.B/SU.C/SU.D+N/SU.F/SU.G+N | SU.A | SU.G+N | 21 | 3345 | 0000000000000000 | 93 | 41 | 6 | 1 |
| /SU.A/SU.B/SU.C/SU.D+N/SU.F/SU.G+N/SU.I | SU.A | SU.I | 20 | 3345 | 0000000000000000 | 93 | 20 | 7 | 1 |
| /SVP01 | SVP01 | SVP01 | 4 | 408 | 0000000000000000 | 24028 | 4 | 1 | 1 |
| /Sanity01 | Sanity01 | Sanity01 | 11 | 408 | 0000000000000000 | 24028 | 11 | 1 | 1 |
| /Sanity1 | Sanity1 | Sanity1 | 1 | 408 | 0000000000000000 | 24028 | 1 | 1 | 1 |
| /TB_HT01 | TB_HT01 | TB_HT01 | 6 | 408 | 0000000000000000 | 24028 | 6 | 1 | 1 |
| /TEST_1 | TEST_1 | TEST_1 | 1 | 408 | 0000000000000000 | 24028 | 1 | 1 | 1 |
| /TK_ST001 | TK_ST001 | TK_ST001 | 5 | 408 | 0000000000000000 | 24028 | 5 | 1 | 1 |
The only differences from your expected output are values in COUNT_WITHIN_DMCID column, I really don't get how they are calculated.
I have an oracle table DM_TEMP_SUMMING_DVC_BY_FW with below columns and sample data. Data below shows
-dmc_id ='408' there are 2109 devices which are having firmware_version='RT1' and it is the first firmware_version because image_prerequisite is null for this firmware_image.
-dmc_id ='408' there are 40 devices which are having firmware_version='RT2' moved from "RT1" and so on.
The requirement is to create the chain of firmware_versions and the count of devices moving through the chain. For example:
Firmware_version movement is RT1-->RT2-->RT3-->RT4
so the count of devices moved from RT1 to RT4 is (RT1+RT2+RT3+RT4)
count of devices moved from RT2 to RT4 is (RT2+RT3+RT4)
count of devices moved from RT3 to RT4 is (RT3+RT4)
count of devices at last firmware_version is RT4
Below is the input data in table DM_TEMP_SUMMING_DVC_BY_FW
+-----------+-------+-----------------+-----------------+------------------+-------------------+
device_count| dmc_id| firmware_version| cg_id |image_prerequisite| count_within_dmcid|
+-----------+-------+-----------------+-----------------+------------------+-------------------+
| 40 | 408 |RT2 |0 |RT1 | 24028 |
| 24 | 408 |RT3 |0 |RT2 | 24028 |
| 18 | 408 |RT4 |0 |RT3 | 24028 |
| 2109 | 408 |RT1 |0 |null | 24028 |
| 1 | 1422 |RT1 |0 |null | 7 |
| 1 | 1422 |RT2 |0 |RT1 | 7 |
| 1 | 408 |RT1 |HFOTA-0000000041 |null | 1 |
| 1 | 408 |RT1 |HFOTA-0000000334 |null | 2 |
| 1 | 408 |RT1 |HFOTA-0000000359 |null | 1 |
| 1 | 408 |RT1 |HFOTA-0000000441 |null | 1 |
| 1 | 408 |RT1 |HFOTA-0000001885 |null | 2 |
| 4 | 408 |SVP01 |0 |null | 24028 |
| 11 | 408 |Sanity01 |0 |null | 24028 |
| 1 | 408 |Sanity1 |0 |null | 24028 |
| 6 | 408 |TB_HT01 |0 |null | 24028 |
| 1 | 408 |TEST_1 |0 |null | 24028 |
| 5 | 408 |TK_ST001 |0 |null | 24028 |
+-----------+-------+-----------------+-----------------+------------------+-------------------+
Query that I have executed:
SELECT
chain,
firmware_version as fw,
device_count as cnt,
dmc_id,
cg_id,
count_within_dmcid,
sum( device_count ) over ( partition by dmc_id, cg_id order by lev desc ) as cumm
FROM (
select t.* , level lev,
sys_connect_by_path( firmware_version, '/' ) as chain
from DM_TEMP_SUMMING_DVC_BY_FW t
START WITH image_prerequisite IS null
CONNECT BY nocycle PRIOR firmware_version=image_prerequisite
AND PRIOR dmc_id = dmc_id
AND PRIOR cg_id = cg_id
) x
order by dmc_id, cg_id, lev desc
;
Results Query is returning:
+-----------------+---------+-----+------+----------------+------------------+----+
chain |fw |cnt |dmc_id| cg_id |count_within_dmcid|cumm|
+-----------------+---------+-----+------+----------------+------------------+----+
|/RT1/RT2/RT3/RT4 | RT4 | 18| 408 | 0 | 24028 | 18|
|/RT1/RT2/RT3 | RT3 | 24| 408 | 0 | 24028 | 42|
|/RT1/RT2 | RT2 | 40| 408 | 0 | 24028 | 82|
|/Sanity1 |Sanity1 | 1 | 408 | 0 | 24028 |2219|
|/TB_HT01 |TB_HT01 | 6 | 408 | 0 | 24028 |2219|
|/Sanity01 |Sanity01 | 11| 408 | 0 | 24028 |2219|
|/SVP01 |SVP01 | 4 | 408 | 0 | 24028 |2219|
|/RT1 | RT1 |2109 | 408 | 0 | 24028 |2219|
|/TEST_1 |TEST_1 | 1 | 408 | 0 | 24028 |2219|
|/TK_ST001 |TK_ST001 | 5 | 408 | 0 | 24028 |2219|
|/RT1 |RT1 | 1 | 408 |HFOTA-0000000041| 1 | 1 |
|/RT1 |RT1 |1 | 408 |HFOTA-0000000334| 2 | 1 |
|/RT1 |RT1 |1 | 408 |HFOTA-0000000359| 1 | 1 |
|/RT1 |RT1 |1 | 408 |HFOTA-0000000441| 1 | 1 |
|/RT1 |RT1 |1 | 408 |HFOTA-0000001885| 2 | 1 |
|/RT1/RT2 |RT2 |1 |1422 | 0 | 7 | 1 |
|/RT1 |RT1 |1 |1422 | 0 | 7 | 2 |
+-----------------+---------+-----+------+----------------+------------------+----+
Expected Results:
+-----------------+---------+-----+------+----------------+------------------+----+
chain |fw |cnt |dmc_id| cg_id |count_within_dmcid|cumm|
+-----------------+---------+-----+------+----------------+------------------+----+
|/RT1/RT2/RT3/RT4 | RT4 | 18| 408 | 0 | 24028 | 18|
|/RT1/RT2/RT3 | RT3 | 24| 408 | 0 | 24028 | 42|
|/RT1/RT2 | RT2 | 40| 408 | 0 | 24028 | 82|
|/Sanity1 |Sanity1 | 1 | 408 | 0 | 24028 | 1 |
|/TB_HT01 |TB_HT01 | 6 | 408 | 0 | 24028 | 6 |
|/Sanity01 |Sanity01 | 11| 408 | 0 | 24028 | 11 |
|/SVP01 |SVP01 | 4 | 408 | 0 | 24028 | 4 |
|/RT1 | RT1 |2109 | 408 | 0 | 24028 |2191|
|/TEST_1 |TEST_1 | 1 | 408 | 0 | 24028 | 1 |
|/TK_ST001 |TK_ST001 | 5 | 408 | 0 | 24028 | 5 |
|/RT1 |RT1 | 1 | 408 |HFOTA-0000000041| 1 | 1 |
|/RT1 |RT1 |1 | 408 |HFOTA-0000000334| 2 | 1 |
|/RT1 |RT1 |1 | 408 |HFOTA-0000000359| 1 | 1 |
|/RT1 |RT1 |1 | 408 |HFOTA-0000000441| 1 | 1 |
|/RT1 |RT1 |1 | 408 |HFOTA-0000001885| 2 | 1 |
|/RT1/RT2 |RT2 |1 |1422 | 0 | 7 | 1 |
|/RT1 |RT1 |1 |1422 | 0 | 7 | 2 |
+-----------------+---------+-----+------+----------------+------------------+----+
Please suggest any solution for this problem.
Thanks in advance!
Another scenario with the split chains -
Input data in DM_TEMP_SUMMING_DVC_BY_FW table.
+-----------+-------+-----------------+-----------------+------------------+-------------------+
device_count| dmc_id| firmware_version| cg_id |image_prerequisite| count_within_dmcid|
+-----------+-------+-----------------+-----------------+------------------+-------------------+
| 5 | 3345 |SU.B |0000000000000000 |SU.A | 93 |
| 6 | 3345 |SU.C |0000000000000000 |SU.B | 93 |
| 8 | 3345 |SU.D |0000000000000000 |SU.C | 93 |
| 8 | 3345 |SU.E |0000000000000000 |SU.C | 93 |
| 20 | 3345 |SU.F |0000000000000000 |SU.D | 93 |
| 20 | 3345 |SU.F |0000000000000000 |SU.E | 93 |
| 10 | 3345 |SU.G |0000000000000000 |SU.F | 93 |
| 11 | 3345 |SU.H |0000000000000000 |SU.F | 93 |
| 20 | 3345 |SU.I |0000000000000000 |SU.G | 93 |
| 20 | 3345 |SU.I |0000000000000000 |SU.H | 93 |
| 5 | 3345 |SU.A |0000000000000000 |null | 93 |
| 40 | 408 |RT2 |0000000000000000 |RT1 | 24028 |
| 24 | 408 |RT3 |0000000000000000 |RT2 | 24028 |
| 18 | 408 |RT4 |0000000000000000 |RT3 | 24028 |
| 2109 | 408 |RT1 |0000000000000000 |null | 24028 |
| 1 | 142 |RT1 |0000000000000000 |null | 7 |
| 1 | 142 |RT2 |0000000000000000 |RT1 | 7 |
| 1 | 408 |RT1 |HFOTA-0000000041 |null | 1 |
| 1 | 408 |RT1 |HFOTA-0000000334 |null | 2 |
| 1 | 408 |RT1 |HFOTA-0000000359 |null | 1 |
| 1 | 408 |RT1 |HFOTA-0000000441 |null | 1 |
| 1 | 408 |RT1 |HFOTA-0000001885 |null | 2 |
| 4 | 408 |SVP01 |0000000000000000 |null | 24028 |
| 11 | 408 |Sanity01 |0000000000000000 |null | 24028 |
| 1 | 408 |Sanity1 |0000000000000000 |null | 24028 |
| 6 | 408 |TB_HT01 |0000000000000000 |null | 24028 |
| 1 | 408 |TEST_1 |0000000000000000 |null | 24028 |
| 5 | 408 |TK_ST001 |0000000000000000 |null | 24028 |
+-----------+-------+-----------------+-----------------+------------------+-------------------+
This query is breaking in the path split scenario data.
SU.A (5) -- Level 1
|
SU.B (5) -- Level 2
|
SU.C (6) -- Level 3
/ \
(8) SU.D SU.E (8) -- Level 4
\ /
SU.F (20) -- Level 5
/ \
(10) SU.G SU.H (11) -- Level 6
\ /
SU.I (20) -- Level 7
Query used:
SELECT chain,
root_fw,
firmware_version,
device_count,
dmc_id,
charging_group_id,
count_within_dmcid,
SUM(device_count) over(PARTITION BY dmc_id, cg_id, root_fw ORDER BY lev DESC),
lev
FROM (SELECT t.*,
LEVEL lev,
sys_connect_by_path(firmware_version, '/') AS chain,
connect_by_root(firmware_version) root_fw
FROM dm_temp_summing_dvc_by_fw t
START WITH image_prerequisite IS NULL
CONNECT BY nocycle PRIOR firmware_version = image_prerequisite
AND PRIOR dmc_id = dmc_id
AND PRIOR cg_id = cg_id) x
ORDER BY dmc_id,
cg_id,
lev DESC;
Ouput query is returning:
+-----------------------------------+--------+--------+-------------+------+----------------+------------------+----+---+
chain |root_fw |fw |device_count |dmc_id| cg_id |count_within_dmcid|cumm|lev|
+-----------------------------------+--------+--------+-------------+------+----------------+------------------+----+---+
|/SU.A/SU.B/SU.C/SU.D/SU.F/SU.G/SU.I|SU.A |SU.I | 20 |3345 |0000000000000000|93 |80 |7 |
|/SU.A/SU.B/SU.C/SU.E/SU.F/SU.H/SU.I|SU.A |SU.I | 20 |3345 |0000000000000000|93 |80 |7 |
|/SU.A/SU.B/SU.C/SU.E/SU.F/SU.G/SU.I|SU.A |SU.I | 20 |3345 |0000000000000000|93 |80 |7 |
|/SU.A/SU.B/SU.C/SU.D/SU.F/SU.H/SU.I|SU.A |SU.I | 20 |3345 |0000000000000000|93 |80 |7 |
|/SU.A/SU.B/SU.C/SU.E/SU.F/SU.G |SU.A |SU.G | 10 |3345 |0000000000000000|93 |122 |6 |
|/SU.A/SU.B/SU.C/SU.D/SU.F/SU.G |SU.A |SU.G | 10 |3345 |0000000000000000|93 |122 |6 |
|/SU.A/SU.B/SU.C/SU.D/SU.F/SU.H |SU.A |SU.H | 11 |3345 |0000000000000000|93 |122 |6 |
|/SU.A/SU.B/SU.C/SU.E/SU.F/SU.H |SU.A |SU.H | 11 |3345 |0000000000000000|93 |122 |6 |
|/SU.A/SU.B/SU.C/SU.E/SU.F |SU.A |SU.F | 20 |3345 |0000000000000000|93 |162 |5 |
|/SU.A/SU.B/SU.C/SU.D/SU.F |SU.A |SU.F | 20 |3345 |0000000000000000|93 |162 |5 |
|/SU.A/SU.B/SU.C/SU.E |SU.A |SU.E | 8 |3345 |0000000000000000|93 |178 |4 |
|/SU.A/SU.B/SU.C/SU.D |SU.A |SU.D | 8 |3345 |0000000000000000|93 |178 |4 |
|/SU.A/SU.B/SU.C |SU.A |SU.C | 6 |3345 |0000000000000000|93 |184 |3 |
|/SU.A/SU.B |SU.A |SU.B | 5 |3345 |0000000000000000|93 |189 |2 |
|/SU.A |SU.A |SU.A | 5 |3345 |0000000000000000|93 |194 |1 |
|/RT1/RT2/RT3/RT4 |RT1 |RT4 | 18 |408 |0000000000000000|24028 |18 |4 |
|/RT1/RT2/RT3 |RT1 |RT3 | 24 |408 |0000000000000000|24028 |42 |3 |
|/RT1/RT2 |RT1 |RT2 | 40 |408 |0000000000000000|24028 |82 |2 |
|/Sanity1 |Sanity1 |Sanity1 | 1 |408 |0000000000000000|24028 |1 |1 |
|/TB_HT01 |TB_HT01 |TB_HT01 | 6 |408 |0000000000000000|24028 |6 |1 |
|/Sanity01 |Sanity01|Sanity01| 11 |408 |0000000000000000|24028 |11 |1 |
|/SVP01 |SVP01 |SVP01 | 4 |408 |0000000000000000|24028 |4 |1 |
|/RT1 |RT1 |RT1 | 2109 |408 |0000000000000000|24028 |2191|1 |
|/TEST_1 |TEST_1 |TEST_1 | 1 |408 |0000000000000000|24028 |1 |1 |
|/TK_ST001 |TK_ST001|TK_ST001| 5 |408 |0000000000000000|24028 |5 |1 |
|/RT1 |RT1 |RT1 | 1 |408 |HFOTA-0000000041|1 |1 |1 |
|/RT1 |RT1 |RT1 | 1 |408 |HFOTA-0000000334|2 |1 |1 |
|/RT1 |RT1 |RT1 | 1 |408 |HFOTA-0000000359|1 |1 |1 |
|/RT1 |RT1 |RT1 | 1 |408 |HFOTA-0000000441|1 |1 |1 |
|/RT1 |RT1 |RT1 | 1 |408 |HFOTA-0000001885|2 |1 |1 |
|/RT1/RT2 |RT1 |RT2 | 1 |1422 |0000000000000000|7 |1 |2 |
|/RT1 |RT1 |RT1 | 1 |1422 |0000000000000000|7 |2 |1 |
+-----------------------------------+--------+--------+-------------+------+----------------+------------------+----+---+
Chain and cumulative counts are coming correct for regural chains A - B- C- D, but if we have split chains then it is doing summary of all the chain generated.
SU.A - 93 A+B+C+D+E+F+G+H+I
SU.B - 88 B+C+D+E+F+G+H+I
SU.C - 83 C+D+E+F+G+H+I
SU.D - 0 (Cummulative count will be zero if we have two or more FW at same level)
SU.E - 0 (Cummulative count will be zero if we have two or more FW at same level)
SU.F - 61 F+G+H+I
SU.G - 0 Cummulative count will be zero if we have two or more FW at same level)
SU.H - 0 Cummulative count will be zero if we have two or more FW at same level)
SU.I - 20 I
Expected output in this split scenario:
+---------------------------------------------+--------+--------+-------------+------+----------------+------------------+----+---+
chain |root_fw |fw |device_count |dmc_id| cg_id |count_within_dmcid|cumm|lev|
+---------------------------------------------+--------+--------+-------------+------+----------------+------------------+----+---+
|/SU.A/SU.B/SU.C/SU.D/SU.E/SU.F/SU.G/SU.H/SU.I|SU.A |SU.I | 20 |3345 |0000000000000000|93 |20 |7 |
|/SU.A/SU.B/SU.C/SU.D/SU.E/SU.F/SU.G/SU.H/ |SU.A |SU.H | 11 |3345 |0000000000000000|93 |0 |6 |
|/SU.A/SU.B/SU.C/SU.D/SU.E/SU.F/SU.G |SU.A |SU.G | 10 |3345 |0000000000000000|93 |0 |6 |
|/SU.A/SU.B/SU.C/SU.D/SU.E/SU.F |SU.A |SU.F | 20 |3345 |0000000000000000|93 |61 |5 |
|/SU.A/SU.B/SU.C/SU.D/SU.E |SU.A |SU.E | 8 |3345 |0000000000000000|93 |0 |4 |
|/SU.A/SU.B/SU.C/SU.D |SU.A |SU.D | 8 |3345 |0000000000000000|93 |0 |4 |
|/SU.A/SU.B/SU.C |SU.A |SU.C | 6 |3345 |0000000000000000|93 |83 |3 |
|/SU.A/SU.B |SU.A |SU.B | 5 |3345 |0000000000000000|93 |88 |2 |
|/SU.A |SU.A |SU.A | 5 |3345 |0000000000000000|93 |93 |1 |
|/RT1/RT2/RT3/RT4 |RT1 |RT4 | 18 |408 |0000000000000000|24028 |18 |4 |
|/RT1/RT2/RT3 |RT1 |RT3 | 24 |408 |0000000000000000|24028 |42 |3 |
|/RT1/RT2 |RT1 |RT2 | 40 |408 |0000000000000000|24028 |82 |2 |
|/Sanity1 |Sanity1 |Sanity1 | 1 |408 |0000000000000000|24028 |1 |1 |
|/TB_HT01 |TB_HT01 |TB_HT01 | 6 |408 |0000000000000000|24028 |6 |1 |
|/Sanity01 |Sanity01|Sanity01| 11 |408 |0000000000000000|24028 |11 |1 |
|/SVP01 |SVP01 |SVP01 | 4 |408 |0000000000000000|24028 |4 |1 |
|/RT1 |RT1 |RT1 | 2109 |408 |0000000000000000|24028 |2191|1 |
|/TEST_1 |TEST_1 |TEST_1 | 1 |408 |0000000000000000|24028 |1 |1 |
|/TK_ST001 |TK_ST001|TK_ST001| 5 |408 |0000000000000000|24028 |5 |1 |
|/RT1 |RT1 |RT1 | 1 |408 |HFOTA-0000000041|1 |1 |1 |
|/RT1 |RT1 |RT1 | 1 |408 |HFOTA-0000000334|2 |1 |1 |
|/RT1 |RT1 |RT1 | 1 |408 |HFOTA-0000000359|1 |1 |1 |
|/RT1 |RT1 |RT1 | 1 |408 |HFOTA-0000000441|1 |1 |1 |
|/RT1 |RT1 |RT1 | 1 |408 |HFOTA-0000001885|2 |1 |1 |
|/RT1/RT2 |RT1 |RT2 | 1 |1422 |0000000000000000|7 |1 |2 |
|/RT1 |RT1 |RT1 | 1 |1422 |0000000000000000|7 |2 |1 |
+---------------------------------------------+--------+--------+-------------+------+----------------+------------------+----+---+
It looks like what you're missing is partitioning on the root firmware_version, which you can get by using connect_by_root(), like so:
WITH dm_temp_summing_dvc_by_fw AS (SELECT 40 device_count, 408 dmc_id, 'RT2' firmware_version, '0000' cg_id, 'RT1' image_prerequisite, 24028 count_within_dmcid FROM dual UNION ALL
SELECT 24 device_count, 408 dmc_id, 'RT3' firmware_version, '0000' cg_id, 'RT2' image_prerequisite, 24028 count_within_dmcid FROM dual UNION ALL
SELECT 18 device_count, 408 dmc_id, 'RT4' firmware_version, '0000' cg_id, 'RT3' image_prerequisite, 24028 count_within_dmcid FROM dual UNION ALL
SELECT 2109 device_count, 408 dmc_id, 'RT1' firmware_version, '0000' cg_id, NULL image_prerequisite, 24028 count_within_dmcid FROM dual UNION ALL
SELECT 1 device_count, 1422 dmc_id, 'RT1' firmware_version, '0000' cg_id, NULL image_prerequisite, 7 count_within_dmcid FROM dual UNION ALL
SELECT 1 device_count, 1422 dmc_id, 'RT2' firmware_version, '0000' cg_id, 'RT1' image_prerequisite, 7 count_within_dmcid FROM dual UNION ALL
SELECT 1 device_count, 408 dmc_id, 'RT1' firmware_version, 'HFOTA1' cg_id, NULL image_prerequisite, 1 count_within_dmcid FROM dual UNION ALL
SELECT 1 device_count, 408 dmc_id, 'RT1' firmware_version, 'HFOTA2' cg_id, NULL image_prerequisite, 2 count_within_dmcid FROM dual UNION ALL
SELECT 1 device_count, 408 dmc_id, 'RT1' firmware_version, 'HFOTA3' cg_id, NULL image_prerequisite, 1 count_within_dmcid FROM dual UNION ALL
SELECT 1 device_count, 408 dmc_id, 'RT1' firmware_version, 'HFOTA4' cg_id, NULL image_prerequisite, 1 count_within_dmcid FROM dual UNION ALL
SELECT 1 device_count, 408 dmc_id, 'RT1' firmware_version, 'HFOTA5' cg_id, NULL image_prerequisite, 2 count_within_dmcid FROM dual UNION ALL
SELECT 4 device_count, 408 dmc_id, 'SVP01' firmware_version, '0000' cg_id, NULL image_prerequisite, 24028 count_within_dmcid FROM dual UNION ALL
SELECT 11 device_count, 408 dmc_id, 'Sanity01' firmware_version, '0000' cg_id, NULL image_prerequisite, 24028 count_within_dmcid FROM dual UNION ALL
SELECT 1 device_count, 408 dmc_id, 'Sanity1' firmware_version, '0000' cg_id, NULL image_prerequisite, 24028 count_within_dmcid FROM dual UNION ALL
SELECT 6 device_count, 408 dmc_id, 'TB_HT01' firmware_version, '0000' cg_id, NULL image_prerequisite, 24028 count_within_dmcid FROM dual UNION ALL
SELECT 1 device_count, 408 dmc_id, 'TEST_1' firmware_version, '0000' cg_id, NULL image_prerequisite, 24028 count_within_dmcid FROM dual UNION ALL
SELECT 5 device_count, 408 dmc_id, 'TK_ST001' firmware_version, '0000' cg_id, NULL image_prerequisite, 24028 count_within_dmcid FROM dual)
SELECT chain,
root_fw,
firmware_version AS fw,
device_count AS cnt,
dmc_id,
cg_id,
lev,
count_within_dmcid,
SUM(device_count) over(PARTITION BY dmc_id, cg_id, root_fw ORDER BY lev DESC) AS cumm
FROM (SELECT t.*,
LEVEL lev,
sys_connect_by_path(firmware_version, '/') AS chain,
connect_by_root(firmware_version) root_fw
FROM dm_temp_summing_dvc_by_fw t
START WITH image_prerequisite IS NULL
CONNECT BY nocycle PRIOR firmware_version = image_prerequisite
AND PRIOR dmc_id = dmc_id
AND PRIOR cg_id = cg_id) x
ORDER BY dmc_id,
cg_id,
lev DESC;
Which gives the results:
CHAIN ROOT_FW FW CNT DMC_ID CG_ID LEV COUNT_WITHIN_DMCID CUMM
----------------- -------- -------- ---------- ---------- ------ ---------- ------------------ ----------
/RT1/RT2/RT3/RT4 RT1 RT4 18 408 0000 4 24028 18
/RT1/RT2/RT3 RT1 RT3 24 408 0000 3 24028 42
/RT1/RT2 RT1 RT2 40 408 0000 2 24028 82
/Sanity1 Sanity1 Sanity1 1 408 0000 1 24028 1
/TB_HT01 TB_HT01 TB_HT01 6 408 0000 1 24028 6
/Sanity01 Sanity01 Sanity01 11 408 0000 1 24028 11
/SVP01 SVP01 SVP01 4 408 0000 1 24028 4
/RT1 RT1 RT1 2109 408 0000 1 24028 2191
/TEST_1 TEST_1 TEST_1 1 408 0000 1 24028 1
/TK_ST001 TK_ST001 TK_ST001 5 408 0000 1 24028 5
/RT1 RT1 RT1 1 408 HFOTA1 1 1 1
/RT1 RT1 RT1 1 408 HFOTA2 1 2 1
/RT1 RT1 RT1 1 408 HFOTA3 1 1 1
/RT1 RT1 RT1 1 408 HFOTA4 1 1 1
/RT1 RT1 RT1 1 408 HFOTA5 1 2 1
/RT1/RT2 RT1 RT2 1 1422 0000 2 7 1
/RT1 RT1 RT1 1 1422 0000 1 7 2
ETA:
With the additional requirement to handle cases where firmewares are at the same level as each other, I *think* this does what you're after:
WITH dm_temp_summing_dvc_by_fw AS (SELECT 40 device_count, 408 dmc_id, 'RT2' firmware_version, '0000' cg_id, 'RT1' image_prerequisite, 24028 count_within_dmcid FROM dual UNION ALL
SELECT 24 device_count, 408 dmc_id, 'RT3' firmware_version, '0000' cg_id, 'RT2' image_prerequisite, 24028 count_within_dmcid FROM dual UNION ALL
SELECT 18 device_count, 408 dmc_id, 'RT4' firmware_version, '0000' cg_id, 'RT3' image_prerequisite, 24028 count_within_dmcid FROM dual UNION ALL
SELECT 2109 device_count, 408 dmc_id, 'RT1' firmware_version, '0000' cg_id, NULL image_prerequisite, 24028 count_within_dmcid FROM dual UNION ALL
SELECT 1 device_count, 1422 dmc_id, 'RT1' firmware_version, '0000' cg_id, NULL image_prerequisite, 7 count_within_dmcid FROM dual UNION ALL
SELECT 1 device_count, 1422 dmc_id, 'RT2' firmware_version, '0000' cg_id, 'RT1' image_prerequisite, 7 count_within_dmcid FROM dual UNION ALL
SELECT 1 device_count, 408 dmc_id, 'RT1' firmware_version, 'HFOTA1' cg_id, NULL image_prerequisite, 1 count_within_dmcid FROM dual UNION ALL
SELECT 1 device_count, 408 dmc_id, 'RT1' firmware_version, 'HFOTA2' cg_id, NULL image_prerequisite, 2 count_within_dmcid FROM dual UNION ALL
SELECT 1 device_count, 408 dmc_id, 'RT1' firmware_version, 'HFOTA3' cg_id, NULL image_prerequisite, 1 count_within_dmcid FROM dual UNION ALL
SELECT 1 device_count, 408 dmc_id, 'RT1' firmware_version, 'HFOTA4' cg_id, NULL image_prerequisite, 1 count_within_dmcid FROM dual UNION ALL
SELECT 1 device_count, 408 dmc_id, 'RT1' firmware_version, 'HFOTA5' cg_id, NULL image_prerequisite, 2 count_within_dmcid FROM dual UNION ALL
SELECT 4 device_count, 408 dmc_id, 'SVP01' firmware_version, '0000' cg_id, NULL image_prerequisite, 24028 count_within_dmcid FROM dual UNION ALL
SELECT 11 device_count, 408 dmc_id, 'Sanity01' firmware_version, '0000' cg_id, NULL image_prerequisite, 24028 count_within_dmcid FROM dual UNION ALL
SELECT 1 device_count, 408 dmc_id, 'Sanity1' firmware_version, '0000' cg_id, NULL image_prerequisite, 24028 count_within_dmcid FROM dual UNION ALL
SELECT 6 device_count, 408 dmc_id, 'TB_HT01' firmware_version, '0000' cg_id, NULL image_prerequisite, 24028 count_within_dmcid FROM dual UNION ALL
SELECT 1 device_count, 408 dmc_id, 'TEST_1' firmware_version, '0000' cg_id, NULL image_prerequisite, 24028 count_within_dmcid FROM dual UNION ALL
SELECT 5 device_count, 408 dmc_id, 'TK_ST001' firmware_version, '0000' cg_id, NULL image_prerequisite, 24028 count_within_dmcid FROM dual UNION ALL
SELECT 5 device_count, 3345 dmc_id, 'SU.B' firmware_version, '0000' cg_id, 'SU.A' image_prerequisite, 93 count_within_dmcid FROM dual UNION ALL
SELECT 6 device_count, 3345 dmc_id, 'SU.C' firmware_version, '0000' cg_id, 'SU.B' image_prerequisite, 93 count_within_dmcid FROM dual UNION ALL
SELECT 8 device_count, 3345 dmc_id, 'SU.D' firmware_version, '0000' cg_id, 'SU.C' image_prerequisite, 93 count_within_dmcid FROM dual UNION ALL
SELECT 8 device_count, 3345 dmc_id, 'SU.E' firmware_version, '0000' cg_id, 'SU.C' image_prerequisite, 93 count_within_dmcid FROM dual UNION ALL
SELECT 20 device_count, 3345 dmc_id, 'SU.F' firmware_version, '0000' cg_id, 'SU.D' image_prerequisite, 93 count_within_dmcid FROM dual UNION ALL
SELECT 20 device_count, 3345 dmc_id, 'SU.F' firmware_version, '0000' cg_id, 'SU.E' image_prerequisite, 93 count_within_dmcid FROM dual UNION ALL
SELECT 10 device_count, 3345 dmc_id, 'SU.G' firmware_version, '0000' cg_id, 'SU.F' image_prerequisite, 93 count_within_dmcid FROM dual UNION ALL
SELECT 11 device_count, 3345 dmc_id, 'SU.H' firmware_version, '0000' cg_id, 'SU.F' image_prerequisite, 93 count_within_dmcid FROM dual UNION ALL
SELECT 20 device_count, 3345 dmc_id, 'SU.I' firmware_version, '0000' cg_id, 'SU.G' image_prerequisite, 93 count_within_dmcid FROM dual UNION ALL
SELECT 20 device_count, 3345 dmc_id, 'SU.I' firmware_version, '0000' cg_id, 'SU.H' image_prerequisite, 93 count_within_dmcid FROM dual UNION ALL
SELECT 5 device_count, 3345 dmc_id, 'SU.A' firmware_version, '0000' cg_id, NULL image_prerequisite, 93 count_within_dmcid FROM dual),
t1 AS (SELECT device_count,
dmc_id,
CASE WHEN COUNT(image_prerequisite) OVER (PARTITION BY dmc_id, cg_id, image_prerequisite) > 1
THEN listagg(firmware_version, '~') WITHIN GROUP (ORDER BY firmware_version) OVER (PARTITION BY dmc_id, cg_id, image_prerequisite)
ELSE firmware_version
END firmware_version,
cg_id,
image_prerequisite,
count_within_dmcid
FROM dm_temp_summing_dvc_by_fw),
t2 AS (SELECT sum(device_count) device_count,
dmc_id,
firmware_version,
cg_id,
image_prerequisite,
count_within_dmcid
FROM t1
GROUP BY dmc_id,
firmware_version,
cg_id,
image_prerequisite,
count_within_dmcid),
t3 AS (SELECT t.*,
LEVEL lev,
sys_connect_by_path(firmware_version, '/') AS chain,
connect_by_root(firmware_version) root_fw,
row_number() OVER (PARTITION BY dmc_id, cg_id, firmware_version, connect_by_root(firmware_version) ORDER BY LEVEL DESC, sys_connect_by_path(firmware_version, '/')) rn
FROM t2 t
START WITH image_prerequisite IS NULL
CONNECT BY nocycle PRIOR regexp_substr(firmware_version, '[^~]*') = image_prerequisite
AND PRIOR dmc_id = dmc_id
AND PRIOR cg_id = cg_id)
SELECT chain,
root_fw,
firmware_version AS fw,
device_count AS cnt,
dmc_id,
cg_id,
lev,
count_within_dmcid,
rn,
SUM(device_count) over(PARTITION BY dmc_id, cg_id, root_fw ORDER BY lev DESC) AS cumm
FROM t3
ORDER BY dmc_id,
cg_id,
lev DESC;
which gives us:
CHAIN ROOT_FW FW CNT DMC_ID CG_ID LEV COUNT_WITHIN_DMCID RN CUMM
--------------------------------------------- ---------- --------------- ---------- ---------- ------ ---------- ------------------ ---------- ----------
/RT1/RT2/RT3/RT4 RT1 RT4 18 408 0000 4 24028 1 18
/RT1/RT2/RT3 RT1 RT3 24 408 0000 3 24028 1 42
/RT1/RT2 RT1 RT2 40 408 0000 2 24028 1 82
/SVP01 SVP01 SVP01 4 408 0000 1 24028 1 4
/RT1 RT1 RT1 2109 408 0000 1 24028 1 2191
/Sanity01 Sanity01 Sanity01 11 408 0000 1 24028 1 11
/Sanity1 Sanity1 Sanity1 1 408 0000 1 24028 1 1
/TB_HT01 TB_HT01 TB_HT01 6 408 0000 1 24028 1 6
/TEST_1 TEST_1 TEST_1 1 408 0000 1 24028 1 1
/TK_ST001 TK_ST001 TK_ST001 5 408 0000 1 24028 1 5
/RT1 RT1 RT1 1 408 HFOTA1 1 1 1 1
/RT1 RT1 RT1 1 408 HFOTA2 1 2 1 1
/RT1 RT1 RT1 1 408 HFOTA3 1 1 1 1
/RT1 RT1 RT1 1 408 HFOTA4 1 1 1 1
/RT1 RT1 RT1 1 408 HFOTA5 1 2 1 1
/RT1/RT2 RT1 RT2 1 1422 0000 2 7 1 1
/RT1 RT1 RT1 1 1422 0000 1 7 1 2
/SU.A/SU.B/SU.C/SU.D~SU.E/SU.F/SU.G~SU.H/SU.I SU.A SU.I 20 3345 0000 7 93 1 20
/SU.A/SU.B/SU.C/SU.D~SU.E/SU.F/SU.G~SU.H SU.A SU.G~SU.H 21 3345 0000 6 93 1 41
/SU.A/SU.B/SU.C/SU.D~SU.E/SU.F SU.A SU.F 20 3345 0000 5 93 1 61
/SU.A/SU.B/SU.C/SU.D~SU.E SU.A SU.D~SU.E 16 3345 0000 4 93 1 77
/SU.A/SU.B/SU.C SU.A SU.C 6 3345 0000 3 93 1 83
/SU.A/SU.B SU.A SU.B 5 3345 0000 2 93 1 88
/SU.A SU.A SU.A 5 3345 0000 1 93 1 93
What this latest query does is first find out if there are firmwares that are at the same level as each other, and if so, we listagg them together (here, I've used ~ as a separator for clarity in the results - there's nothing to stop you from using the same separator as you use in the sys_connect_by_path).
Once we have that, we can do the connect by, but we need to look at just the first entry in the newly calculated firmware column (otherwise we won't find a match in the image_prerequisite column). Then it's just calculating the results in the same way the previous query did.