sql >> Database >  >> RDS >> Oracle

Hoe tellingen uitvoeren op een Oracle-hiërarchische tabel op basis van Parent Link?

Probeer dit om de gegevens te selecteren:

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

Op een testset van 39000 records kostte het een Intel Core i5 met Oracle 11.2 (en flushed buffer cache) ongeveer 0,15 sec om dit te berekenen. Ik hoop dat het snel genoeg is om aan uw behoeften te voldoen.

Om de doeltabel met deze gegevens bij te werken, doorloopt u de bovenstaande SELECT en update je link_counts tabel iteratief, of gebruik gewoon de MERGE verklaring:

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

De MERGE gaat ervan uit dat de GROUP_ID is een primaire/unieke sleutel in de link_counts tafel. De daadwerkelijke definitie van de tech_values tabel in de oorspronkelijke vraag ondersteunt deze veronderstelling.

Een spoel van een testrun in SQL*Plus is als volgt:

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



  1. Sqlalchemy.exc.Operationele fout:(psycopg2.Operationele fout)

  2. Maak onderscheid tussen NULL's bij gebruik van group by ... met rollup

  3. Een kolom uitsluiten met SELECT * [behalve columnA] FROM tableA?

  4. SQLSTATE [HY000] [1045] Toegang geweigerd voor gebruiker 'gebruikersnaam'@'localhost' met behulp van CakePHP