2017-02-22 74 views
8

mam hierarchiczną tabelę o nazwie Employee_Hierarchy w wyroczni z nazwami kolumn entity_code, parent_entity_code, ENTITY_NAME i entity_role bez cyklu. Mając niższy wiek podrzędny w innej tabeli o nazwie Klient połączony z najniższym dzieckiem podrzędnym tabeli hierarchicznej z kodem entity. Muszę wyświetlić dane w hierarchii w jednym wierszu, do której nazwa kolumny zostanie dodana do roli. PrzykładOracle struktury drzewa wyświetlanych Hierarchia danych w pojedyncze Row innej kolumny

próbki:

struktury drzewa:

enter image description here

hierarchiczne Tabela:

enter image description here

Tabela Dolnej najbardziej dziecka:

enter image description here

Oczekiwany wynik:

enter image description here

Czy istnieje sposób, aby uzyskać ex oczekiwany wynik poprzez zapytanie o Oracle? Oczekiwany wynik zależy od danych wejściowych, co oznacza, że ​​nie zawsze zaczyna się od elementu głównego, może zaczynać się od dowolnego węzła, na przykład od zespołu prowadzącego (Shail) do najniższego elementu podrzędnego.

(Uwaga: Jeżeli górna hierarchia brakuje wtedy parent_code bieżącego węzła będzie parent_code jego górnej hierarchii i brakujący element hierarchii będzie pusty w oczekiwany rezultat.)

z góry dzięki.

+2

ten zakłada stałą liczbę poziomów w hierarchii: Klient mathguy

+2

Czy używasz MySQL lub Oracle? (Prawdopodobnie różne odpowiedzi.) – jarlh

+0

@jarlh: Używam Oracle. –

Odpowiedz

4
select  h.Manager_entity_code 
      ,h.Manager_entity_name 
      ,h.Team_Lead_entity_code 
      ,h.Team_Lead_entity_name 
      ,h.Developer_entity_code 
      ,h.Developer_entity_name 
      ,c.client_name 

from  (select  trim (both ',' from sys_connect_by_path (case when entity_role = 'Manager' then entity_code end,',')) as Manager_entity_code 
         ,trim (both ',' from sys_connect_by_path (case when entity_role = 'Manager' then entity_name end,',')) as Manager_entity_name 
         ,trim (both ',' from sys_connect_by_path (case when entity_role = 'Team-Lead' then entity_code end,',')) as Team_Lead_entity_code 
         ,trim (both ',' from sys_connect_by_path (case when entity_role = 'Team-Lead' then entity_name end,',')) as Team_Lead_entity_name 
         ,trim (both ',' from sys_connect_by_path (case when entity_role = 'Developer' then entity_code end,',')) as Developer_entity_code 
         ,trim (both ',' from sys_connect_by_path (case when entity_role = 'Developer' then entity_name end,',')) as Developer_entity_name 

      from  hierarchical_table 

      where  connect_by_isleaf = 1 

      connect by parent_entity_code = prior entity_code 

      start with entity_code = 100 
      ) h 

      join client_table c 

      on c.entity_code = 
       h.Developer_entity_code 

order by h.Manager_entity_code 
      ,h.Team_Lead_entity_code 
      ,h.Developer_entity_code 
; 

+---------------------+---------------------+-----------------------+-----------------------+-----------------------+-----------------------+-------------+ 
| MANAGER_ENTITY_CODE | MANAGER_ENTITY_NAME | TEAM_LEAD_ENTITY_CODE | TEAM_LEAD_ENTITY_NAME | DEVELOPER_ENTITY_CODE | DEVELOPER_ENTITY_NAME | CLIENT_NAME | 
+---------------------+---------------------+-----------------------+-----------------------+-----------------------+-----------------------+-------------+ 
|     100 | Mack    |     200 | Shail     |     500 | Neha     | Tata  | 
|     100 | Mack    |     300 | Jack     |     600 | Rocky     | Rel   | 
|     100 | Mack    |     300 | Jack     |     600 | Rocky     | Voda  | 
|     100 | Mack    |     300 | Jack     |     600 | Rocky     | Airtel  | 
+---------------------+---------------------+-----------------------+-----------------------+-----------------------+-----------------------+-------------+ 

Dla start with entity_code = 300

+---------------------+---------------------+-----------------------+-----------------------+-----------------------+-----------------------+-------------+ 
| MANAGER_ENTITY_CODE | MANAGER_ENTITY_NAME | TEAM_LEAD_ENTITY_CODE | TEAM_LEAD_ENTITY_NAME | DEVELOPER_ENTITY_CODE | DEVELOPER_ENTITY_NAME | CLIENT_NAME | 
+---------------------+---------------------+-----------------------+-----------------------+-----------------------+-----------------------+-------------+ 
| (null)    | (null)    |     300 | Jack     |     600 | Rocky     | Airtel  | 
| (null)    | (null)    |     300 | Jack     |     600 | Rocky     | Voda  | 
| (null)    | (null)    |     300 | Jack     |     600 | Rocky     | Rel   | 
+---------------------+---------------------+-----------------------+-----------------------+-----------------------+-----------------------+-------------+ 
+0

dziękuję, Dudu, zrobiłeś mój dzień. Oba rozwiązania działają dobrze. Ponieważ mam tysiące danych do przetworzenia przy użyciu hierarchii, które rozwiązanie powinienem preferować (myślę, że wykonanie regex zajmuje więcej czasu). –

2

Oto jeden sposób, aby to zrobić, używając złączeń. Alternatywą jest połączenie dwóch tabel i wykonanie kwerendy hierarchicznej - ale to naprawdę to samo (zapytanie hierarchiczne to nic innego jak rekurencyjne samołączenie).

with 
    hierarchical_table (entity_code, entity_name, entity_role, parent_entity_code) as (
     select 100, 'Mack' , 'Manager', cast (null as number) from dual union all 
     select 200, 'Shail', 'Team-Lead', 100     from dual union all 
     select 300, 'Jack' , 'Team-Lead', 100     from dual union all 
     select 400, 'Teju' , 'Developer', 200     from dual union all 
     select 500, 'Neha' , 'Developer', 200     from dual union all 
     select 600, 'Rocky', 'Developer', 300     from dual 
    ), 
    client_table (entity_code, client_name, address) as (
     select 600, 'Voda' , 'Pune' from dual union all 
     select 600, 'Rel' , 'Mumbai' from dual union all 
     select 600, 'Airtel', 'Pune' from dual union all 
     select 500, 'Tata' , 'Mumbai' from dual 
    ) 
-- end of test data (not part of the solution) 
-- SQL query begins BELOW THIS LINE; use your actual table names 
select h1.entity_code as manager_code, h1.entity_name as manager_name, 
     h2.entity_code as teamlead_code, h2.entity_name as teamlead_name, 
     h3.entity_code as developer_code, h3.entity_name as developer_name, 
     c.client_name 
from  hierarchical_table h1 left join hierarchical_table h2 
             on h2.parent_entity_code = h1.entity_code 
           left join hierarchical_table h3 
             on h3.parent_entity_code = h2.entity_code 
           left join client_table c 
             on c.entity_code = h3.entity_code 
where h1.parent_entity_code is null 
order by manager_code, teamlead_code, developer_code, client_name 
; 

Wyjście:

MANAGER_CODE MANAGER_NAME TEAMLEAD_CODE TEAMLEAD_NAME DEVELOPER_CODE DEVELOPER_NAME CLIENT 
------------ ------------ ------------- ------------- -------------- -------------- ------ 
     100 Mack     200 Shail     400 Teju 
     100 Mack     200 Shail     500 Neha   Tata 
     100 Mack     300 Jack      600 Rocky   Airtel 
     100 Mack     300 Jack      600 Rocky   Rel 
     100 Mack     300 Jack      600 Rocky   Voda 

5 rows selected. 
+0

dziękuję za rozwiązanie, ale w powyższym rozwiązaniu cykl zawsze zaczyna się od elementu root, gdzie jest parent_entity_code jest pusty, a nazwa kolumny jest stała, Ale mam scenariusze, w których cykl może rozpoczynać się pomiędzy hierarchią i będę musiał wyświetlić hierarchia od tego punktu do najniższego punktu, dlatego wspominałem o zachowaniu nazwy kolumny jako nazwy roli. –

+0

@ShaileshYadav - Przykro mi, ale nie rozumiem. Zakładam, że przez "cykl" rozumiesz "drzewo" (nie widzę w tym żadnych cykli). Następnie komentujesz nazwy kolumn. Oczywiście kontrolujesz, jakie są nazwy kolumn (w samym zapytaniu); Użyłem dokładnie twoich imion, właśnie opuściłem "entity" (i zrobiłem to tylko dlatego, że ** Output ** pasuje do ekranu bez przewijania). Trochę o konieczności uruchomienia zapytania z punktu pośredniego - co ma wspólnego z nazwami kolumn? (Prawdopodobnie nic.) – mathguy

+0

@ShaileshYadav - A jeśli jest coś jeszcze, to zapytanie nie działa, ponieważ nie radzi sobie z tymi sytuacjami - gdzie jest dyskusja na temat innych sytuacji w oryginalnym poście? A może zmieniasz swoje wymagania PO rozwiązaniu twojego oryginalnego pytania w całości? Tak nie działa! – mathguy

2
select  regexp_substr (h.entity,'Manager~([^~]*)~'   ,1,1,'',1) as Manager_entity_code   
      ,regexp_substr (h.entity,'Manager~([^~]*)~([^,]*)' ,1,1,'',2) as Manager_entity_name 
      ,regexp_substr (h.entity,'Team-Lead~([^~]*)~'  ,1,1,'',1) as Team_Lead_entity_code 
      ,regexp_substr (h.entity,'Team-Lead~([^~]*)~([^,]*)',1,1,'',2) as Team_Lead_entity_name 
      ,regexp_substr (h.entity,'Developer~([^~]*)~'  ,1,1,'',1) as Developer_entity_code 
      ,regexp_substr (h.entity,'Developer~([^~]*)~([^,]*)',1,1,'',2) as Developer_entity_name 
      ,c.client_name 

from  (select  sys_connect_by_path (entity_role || '~' || entity_code || '~' || entity_name,',') as entity 
         ,entity_code 

      from  hierarchical_table 

      where  connect_by_isleaf = 1 

      connect by parent_entity_code = prior entity_code 

      start with entity_code = 200 
      ) h 

      join client_table c 

      on c.entity_code = 
       h.entity_code 

order by Manager_entity_code 
      ,Team_Lead_entity_code 
      ,Developer_entity_code 
; 

+---------------------+---------------------+-----------------------+-----------------------+-----------------------+-----------------------+-------------+ 
| MANAGER_ENTITY_CODE | MANAGER_ENTITY_NAME | TEAM_LEAD_ENTITY_CODE | TEAM_LEAD_ENTITY_NAME | DEVELOPER_ENTITY_CODE | DEVELOPER_ENTITY_NAME | CLIENT_NAME | 
+---------------------+---------------------+-----------------------+-----------------------+-----------------------+-----------------------+-------------+ 
|     100 | Mack    |     200 | Shail     |     500 | Neha     | Tata  | 
|     100 | Mack    |     300 | Jack     |     600 | Rocky     | Rel   | 
|     100 | Mack    |     300 | Jack     |     600 | Rocky     | Voda  | 
|     100 | Mack    |     300 | Jack     |     600 | Rocky     | Airtel  | 
+---------------------+---------------------+-----------------------+-----------------------+-----------------------+-----------------------+-------------+ 

Dla start with entity_code = 600

+---------------------+---------------------+-----------------------+-----------------------+-----------------------+-----------------------+-------------+ 
| MANAGER_ENTITY_CODE | MANAGER_ENTITY_NAME | TEAM_LEAD_ENTITY_CODE | TEAM_LEAD_ENTITY_NAME | DEVELOPER_ENTITY_CODE | DEVELOPER_ENTITY_NAME | CLIENT_NAME | 
+---------------------+---------------------+-----------------------+-----------------------+-----------------------+-----------------------+-------------+ 
| (null)    | (null)    | (null)    | (null)    |     600 | Rocky     | Airtel  | 
| (null)    | (null)    | (null)    | (null)    |     600 | Rocky     | Voda  | 
| (null)    | (null)    | (null)    | (null)    |     600 | Rocky     | Rel   | 
+---------------------+---------------------+-----------------------+-----------------------+-----------------------+-----------------------+-------------+ 
3

w zapytaniu wyników można się spodziewać pewnych ról mieć pewną pozycję w hierarchii. Manager jest na pierwszym poziomie, lider zespołu jest drugi, deweloperzy są na trzecim miejscu. Możesz więc traktować swoją hierarchiczną tabelę tak, jakby jej nie było. To sprawia, że ​​kwerenda bardzo czytelny:

with manager as (select * from employee_hierarchy where entity_role = 'Manager') 
    , teamleader as (select * from employee_hierarchy where entity_role = 'Team-Lead') 
    , developer as (select * from employee_hierarchy where entity_role = 'Developer') 
select 
    m.entity_code as manager_entity_code, 
    m.entity_name as manager_entity_name, 
    t.entity_code as team_lead_entity_code, 
    t.entity_name as team_lead__entity_name, 
    d.entity_code as developer_entity_code, 
    d.entity_name as developer_entity_name, 
    c.client_name 
from manager m 
join teamleader t on t.parent_entity_code = m.entity_code 
join developer d on d.parent_entity_code = t.entity_code 
left join client_table c on c.entity_code = d.entity_code; 

A jeśli chcesz ograniczyć wyniki do Departamentu lider zespołu Shail, wystarczy dodać według WHERE klauzuli:

where t.entity_name = 'Shail'