簡體   English   中英

where子句與connect by和Create查詢的相互作用,以獲取層次結構中的下一級

[英]Interaction of where clause with connect by And Creating query to fetch next level in a hierarchy

表:

create table temp_hierarchy_define (dept varchar2(25), parent_dept varchar2(25))
create table temp_employee (empid number(1), empname varchar2(50), dept varchar2(25), salary number(10))

數據

Select 'COMPANY' dept   , 'COMPANY' parent_dept  From Dual Union All
Select 'IT'        , 'COMPANY'  From Dual Union All
Select 'MARKET'    , 'COMPANY'  From Dual Union All
Select 'ITSEC'     , 'IT'       From Dual Union All
Select 'ITDBA'     , 'IT'       From Dual Union All
Select 'ITDBAORC'  , 'ITDBA'    From Dual Union All
Select 'ITDBASQL'  , 'ITDBA'    From Dual

select 1 empid, 'Rohan-ITDBASQL' empname   ,'ITDBASQL' dept ,10 salary from dual union all
select 2, 'Raj-ITDBAORC'     ,'ITDBAORC'  ,20 from dual union all
select 3, 'Roy-ITDBA'        ,'ITDBA'     ,30 from dual union all
select 4, 'Ray-MARKET'       ,'MARKET'    ,40 from dual union all
select 5, 'Roopal-IT'        ,'IT'        ,50 from dual union all
select 6, 'Ramesh-ITSEC'     ,'ITSEC'     ,60 from dual 

需求

匯總所有IT部門的薪水:

類別工資

5,50

ITSEC,60

ITDBA,60

匯總所有公司部門的工資:

類別工資

IT,170

市場的40

匯總所有ITDBA部門的薪水:

類別工資

3,30

ITDBASQL,10

ITDBAORC,20

您會注意到,我們正在嘗試根據層次結構中的下一個層次進行總結。 如果任何一個emp已經屬於該級別,那么我們需要向員工展示。

試用查詢:

Select Category,sum(salary) from (
Select 
NVL((Select dept.dept from temp_hierarchy_define dept
               Where dept.parent_dept = 'IT'
               And dept.dept != 'IT' 
               Start With dept.dept = emp.dept
               Connect by NOCYCLE dept.dept = Prior dept.parent_dept
               and prior dept.dept is not null),emp.empid) category,
emp.*
From temp_employee emp
Where emp.DEPT in
(Select dept.dept from temp_hierarchy_define dept
Start With dept.dept = 'IT' 
connect by nocycle prior dept.dept = dept.parent_dept) ) Group by Category

問題和疑問:

  1. 此查詢在所有情況下是否都能正常運行。 還是有更好的方法呢?
  2. 條件如何與之交互作用。 例如,在子查詢中,我們使用parent_dept = 'IT'進行過濾,但是在通過某些emp開始連接時,可能具有parent_dept = 'ITDBASQL' ,它也是IT的一部分。 我很難理解工作流程。

感謝您的時間和協助。

還是有更好的方法呢?

這是等效查詢,每個表只需要掃描一次表。 您將需要確定您的查詢或該查詢對於您的數據/索引/等是否更有效。

SQL小提琴

Oracle 11g R2架構設置

create table temp_hierarchy_define (
  dept varchar2(25), parent_dept varchar2(25));
create table temp_employee (
  empid number(1), empname varchar2(50), dept varchar2(25), salary number(10));

INSERT INTO temp_hierarchy_define( dept, parent_dept )
Select 'COMPANY'   , 'COMPANY'  From Dual Union All
Select 'IT'        , 'COMPANY'  From Dual Union All
Select 'MARKET'    , 'COMPANY'  From Dual Union All
Select 'ITSEC'     , 'IT'       From Dual Union All
Select 'ITDBA'     , 'IT'       From Dual Union All
Select 'ITDBAORC'  , 'ITDBA'    From Dual Union All
Select 'ITDBASQL'  , 'ITDBA'    From Dual;

INSERT INTO temp_employee( empid, empname, dept, salary )
select 1, 'Rohan-ITDBASQL'   ,'ITDBASQL'  ,10 from dual union all
select 2, 'Raj-ITDBAORC'     ,'ITDBAORC'  ,20 from dual union all
select 3, 'Roy-ITDBA'        ,'ITDBA'     ,30 from dual union all
select 4, 'Ray-MARKET'       ,'MARKET'    ,40 from dual union all
select 5, 'Roopal-IT'        ,'IT'        ,50 from dual union all
select 6, 'Ramesh-ITSEC'     ,'ITSEC'     ,60 from dual;

查詢1

SELECT dept,
       SUM( salary )
FROM   (
  SELECT CASE
         WHEN lvl = 1 AND h.parent_dept = e.dept
         THEN CAST( e.empid AS VARCHAR2(25) )
         ELSE root_dept
         END AS dept,
         e.empid,
         e.salary
  FROM   ( SELECT CONNECT_BY_ROOT( dept ) AS root_dept,
                  h.*,
                  LEVEL AS lvl,
                  ROW_NUMBER() OVER ( PARTITION BY parent_dept ORDER BY ROWNUM ) AS rn
           FROM   temp_hierarchy_define h
           WHERE  parent_dept != dept
           START WITH h.parent_dept = 'IT'
           CONNECT BY NOCYCLE PRIOR h.dept = h.parent_dept
         ) h
         LEFT OUTER JOIN
         temp_employee e
         ON (  h.dept = e.dept
            OR ( h.parent_dept = e.dept AND h.lvl = 1 AND h.rn = 1)    
            )
)
GROUP BY dept

結果

|  DEPT | SUM(SALARY) |
|-------|-------------|
| ITDBA |          60 |
|     5 |          50 |
| ITSEC |          60 |

您可以單獨運行查詢以查明它們在做什么:

SELECT CONNECT_BY_ROOT( dept ) AS root_dept,
       h.*,
       LEVEL AS lvl,
       ROW_NUMBER() OVER ( PARTITION BY parent_dept ORDER BY ROWNUM ) AS rn
FROM   temp_hierarchy_define h
WHERE  parent_dept != dept
START WITH h.parent_dept = 'IT'
CONNECT BY NOCYCLE PRIOR h.dept = h.parent_dept

僅列出層次結構中的所有行,並使用CONNECT_BY_ROOT將部門設置為層次結構分支的根。 LEVELROW_NUMBER()用於查找層次結構頂部的第一行。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM