Pour sélectionner les données, essayez ceci :
with xyz as (
select tech_type,
connect_by_root(link_id) as root_link_id,
connect_by_root(group_id) as root_group_id
from tech_values
start with parent_group_id = 0
connect by prior group_id = parent_group_id
)
select root_link_id, root_group_id,
a_tech_type as tech_type_a, b_tech_type as tech_type_b, c_tech_type as tech_type_c
from xyz pivot (
count(1) as tech_type
for tech_type in (
'A' as A,
'B' as B,
'C' as C
))
;
Sur un ensemble de tests de 39 000 enregistrements, il a fallu environ 0,15 seconde à un processeur Intel Core i5 avec Oracle 11.2 (et un cache de tampon vidé) pour calculer cela. J'espère qu'il sera assez rapide pour satisfaire vos besoins.
Pour mettre à jour la table cible avec ces données, bouclez sur le SELECT
ci-dessus et mettez à jour vos link_counts
table de manière itérative, ou utilisez simplement le MERGE
déclaration :
merge into link_counts T
using (
with xyz as (
select tech_type,
connect_by_root(link_id) as root_link_id,
connect_by_root(group_id) as root_group_id
from tech_values X
start with parent_group_id = 0
connect by prior group_id = parent_group_id
)
select *
from xyz pivot (
count(1) as tech_type
for tech_type in (
'A' as A,
'B' as B,
'C' as C
))
) S
on ( T.group_id = S.root_group_id )
when matched then
update
set T.tech_type_a = S.a_tech_type,
T.tech_type_b = S.b_tech_type,
T.tech_type_c = S.c_tech_type
when not matched then
insert (link_id, group_id, tech_type_a, tech_type_b, tech_type_c)
values (S.root_link_id, S.root_group_id, S.a_tech_type, S.b_tech_type, S.c_tech_type)
;
Le MERGE
suppose que le GROUP_ID
est une clé primaire/unique dans le link_counts
table. La définition réelle des tech_values
tableau dans la question d'origine confirme cette hypothèse.
Un spool d'exécution de test dans SQL*Plus se présente comme suit :
SQL>
SQL> select count(1)
2 from user_indexes
3 where table_name = 'TECH_VALUES'
4 ;
COUNT(1)
----------
0
SQL>
SQL> select count(1)
2 from user_constraints
3 where table_name = 'TECH_VALUES'
4 and constraint_type != 'C'
5 ;
COUNT(1)
----------
0
SQL>
SQL> alter system flush buffer_cache;
System altered.
SQL> alter system flush shared_pool;
System altered.
SQL>
SQL> select systimestamp from dual;
SYSTIMESTAMP
---------------------------------------------------------------------------
08.06.14 23:18:40,053000 +02:00
SQL>
SQL> select tech_type, count(1)
2 from tech_values
3 where parent_group_id != 0
4 group by rollup(tech_type);
T COUNT(1)
- ----------
A 20048
B 39984
C 19984
80016
SQL>
SQL> select systimestamp from dual;
SYSTIMESTAMP
---------------------------------------------------------------------------
08.06.14 23:18:40,144000 +02:00
SQL>
SQL> alter system flush buffer_cache;
System altered.
SQL> alter system flush shared_pool;
System altered.
SQL>
SQL> select systimestamp from dual;
SYSTIMESTAMP
---------------------------------------------------------------------------
08.06.14 23:18:40,246000 +02:00
SQL>
SQL> with xyz as (
2 select connect_by_root(link_id) as root_link_id, connect_by_root(group_id) as root_group_id, tech_type
3 from tech_values X
4 start with parent_group_id = 0
5 connect by prior group_id = parent_group_id
6 )
7 select *
8 from xyz pivot (
9 count(1) as tech_type
10 for tech_type in (
11 'A' as A,
12 'B' as B,
13 'C' as C
14 ));
ROOT_LINK_ID ROOT_GROUP_ID A_TECH_TYPE B_TECH_TYPE C_TECH_TYPE
---------------------------------------------------------------- ------------- ----------- ----------- -----------
LETTER_B 1800 3667 7482 3854
LETTER_B 200 3712 7583 3708
LETTER_C 300 6326 12450 6229
LETTER_A 100 6343 12469 6193
SQL>
SQL> select *
2 from table(dbms_xplan.display_cursor())
3 ;
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SQL_ID 59hmrtw6q3f4u, child number 0
-------------------------------------
with xyz as ( select connect_by_root(link_id) as root_link_id,
connect_by_root(group_id) as root_group_id, tech_type from
tech_values X start with parent_group_id = 0 connect by prior
group_id = parent_group_id ) select * from xyz pivot ( count(1)
as tech_type for tech_type in ( 'A' as A,
'B' as B, 'C' as C ))
Plan hash value: 3833790953
-------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 563 (100)| |
| 1 | HASH GROUP BY PIVOT | | 29102 | 1420K| 563 (1)| 01:23:35 |
| 2 | VIEW | | 29102 | 1420K| 1044 (47)| 02:35:00 |
|* 3 | CONNECT BY WITH FILTERING| | | | | |
|* 4 | TABLE ACCESS FULL | TECH_VALUES | 4 | 84 | 187 (0)| 00:27:46 |
|* 5 | HASH JOIN | | 29098 | 966K| 375 (1)| 00:55:41 |
| 6 | CONNECT BY PUMP | | | | | |
| 7 | TABLE ACCESS FULL | TECH_VALUES | 80020 | 1641K| 187 (0)| 00:27:46 |
-------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - access("PARENT_GROUP_ID"=PRIOR NULL)
4 - filter("PARENT_GROUP_ID"=0)
5 - access("connect$_by$_pump$_002"."prior group_id "="PARENT_GROUP_ID")
31 rows selected.
SQL>
SQL> select systimestamp from dual;
SYSTIMESTAMP
---------------------------------------------------------------------------
08.06.14 23:18:40,805000 +02:00
SQL>
SQL> spool off