2015-12-21 43 views
0

嗨,我有一個SQL語句使用connect by prior。我想通過特定的where條件獲取路徑。以下SQL工作正常,但我不想只獲得匹配條件的單個行,我還想獲取每個父記錄(垂直向上層次結構)。在Oracle中使用先前的垂直而不是水平的連接獲取路徑層級?

SELECT SUBSTR(SYS_CONNECT_BY_PATH(R.CALCULATION_PLAN_CODE, '.'),4) CODE_PATH, 
     SUBSTR(SYS_CONNECT_BY_PATH(R.CALCULATION_PLAN_NAME, ' > '),29) NAME_PATH,   
     R.CALCULATION_PLAN_CODE, 
     R.CALCULATION_PLAN_NAME   
    FROM PRM.MOVABLE_CALCULATION_PLAN R 
    WHERE R.RELATED_YEAR = :relatedYear 
    AND R.CALCULATION_PLAN_PARENT_OID != 0 
    AND REGEXP_LIKE (R.CALCULATION_PLAN_NAME,'ROL') 
    AND CONNECT_BY_ISLEAF = 1 
START WITH R.OID = 
      (SELECT R1.OID 
      FROM PRM.MOVABLE_CALCULATION_PLAN R1 
      WHERE (R1.CALCULATION_PLAN_PARENT_OID IS NULL OR R1.CALCULATION_PLAN_PARENT_OID = 0) AND R1.RELATED_YEAR=:relatedYear) CONNECT_BY_PRIOR R.OID = R.CALCULATION_PLAN_PARENT_OID; 

我不希望這樣的輸出:result by query 我希望它是這樣的:

150  İLK MADDE VE MALZEMELER 
150.1  İLK MADDE VE MALZEMELER > KIRTASİYE MALZEMELERİ GRUBU 
150.1.1 İLK MADDE VE MALZEMELER > KIRTASİYE MALZEMELERİ GRUBU > ROL <----- 


150  İLK MADDE VE MALZEMELER 
150.1  İLK MADDE VE MALZEMELER > KIRTASİYE MALZEMELERİ GRUBU 
150.1.1 İLK MADDE VE MALZEMELER > KIRTASİYE MALZEMELERİ GRUBU > YAZI ARAÇLARI 
150.1.1.1 İLK MADDE VE MALZEMELER > KIRTASİYE MALZEMELERİ GRUBU > YAZI ARAÇLARI > ROLLER KALEM <----- 

如何實現這一目標?

在此先感謝

+0

刪除'AND REGEXP_LIKE(R.CALCULATION_PLAN_NAME,'ROL')'也許? – Timekiller

+0

@Timekiller,如果我刪除它,如何通過名稱進行搜索。我想使用類似運算符按名稱搜索,然後我正在等待看到一個或多個像上面顯示的樹狀樹。 –

+0

有沒有人評論它? –

回答

0

一個解決方案將需要解決你的表不止一次,因爲你需要的輸出可以有重複(如「150.1」)可能導致利率兩個不同的葉子部分路徑,所以它會發生兩次(或更多)。

請注意,您不需要重複start with子句中的where條件。無論如何也應用它們,也用於起始記錄。

下面是該查詢:

SELECT NODE.CODE_PATH, NODE.NAME_PATH FROM 
     (
     SELECT  OID, 
       SYS_CONNECT_BY_PATH(R.OID, ',') OID_PATH 
     FROM  MOVABLE_CALCULATION_PLAN R 
     WHERE  REGEXP_LIKE (R.CALCULATION_PLAN_NAME,'ROL') 
       AND CONNECT_BY_ISLEAF = 1 
       AND R.RELATED_YEAR = :relatedYear 
     START WITH NVL(CALCULATION_PLAN_PARENT_OID, 0) = 0 
     CONNECT BY PRIOR R.OID = R.CALCULATION_PLAN_PARENT_OID 
    ) LEAF 
INNER JOIN 
     (
     SELECT  SUBSTR(SYS_CONNECT_BY_PATH(R.CALCULATION_PLAN_CODE, '.'),2) CODE_PATH, 
       SUBSTR(SYS_CONNECT_BY_PATH(R.CALCULATION_PLAN_NAME, ' > '),4) NAME_PATH, 
       OID, 
       SYS_CONNECT_BY_PATH(R.OID, ',') OID_PATH 
     FROM  MOVABLE_CALCULATION_PLAN R 
     START WITH NVL(CALCULATION_PLAN_PARENT_OID, 0) = 0 
     CONNECT BY PRIOR R.OID = R.CALCULATION_PLAN_PARENT_OID 
    ) NODE 
ON NODE.OID = LEAF.OID 
OR LEAF.OID_PATH LIKE '%,' || NODE.OID || ',%' 

結果:

CODE_PATH NAME_PATH 
---------- ------------------------------------------------------------ 
150   İLK MADDE VE MALZEMELER 
150.1  İLK MADDE VE MALZEMELER > KIRTASİYE MALZEMELERİ GRUBU 
150.1.1  İLK MADDE VE MALZEMELER > KIRTASİYE MALZEMELERİ GRUBU > ROL 
150   İLK MADDE VE MALZEMELER 
150.1  İLK MADDE VE MALZEMELER > KIRTASİYE MALZEMELERİ GRUBU 
150.1.1  İLK MADDE VE MALZEMELER > KIRTASİYE MALZEMELERİ GRUBU > YAZI ARAÇLARI 
150.1.1.1 İLK MADDE VE MALZEMELER > KIRTASİYE MALZEMELERİ GRUBU > YAZI ARAÇLARI > ROL 

而一個fiddle

想法是,在第一個子選擇中,您選擇葉子,並提供where條件。然後,你做另一個子選擇,其選擇所有節點與他們的路徑,沒有任何過濾。最後,將這些節點與第一個過濾的葉節點的下降線匹配。

+0

這是一個很好的嘗試,但我認爲OP只想顯示* leaf *包含'ROL'的樹木。即使在你的小提琴中,它也會顯示ID爲5的組,其中包含其他條目。此外,由於OR ORECTECT_BY_ISLEAF = 0,你的查詢將顯示所有不包含'ROL'的組 - 看你自己,http://sqlfiddle.com/#!4/c4e4f/1 – Timekiller

+0

謝謝指出。我更新了查詢來處理這個問題。 – trincot

0

你想要的是相當複雜的,但它是可以解決的。但是,您需要構建多個樹:通過第一個查詢,您通過以連接,以葉單位開始,構建分支到根節點,並跟蹤您正在構建分支的葉,使用connect_by_root函數。然後,在第二個查詢中,您基於第一個查詢的結果connect by,這次按照適當的順序,但是另外匹配您之前跟蹤的葉ID。

with Q as 
(
SELECT CONNECT_BY_ROOT(R.OID) leafid, R.* 
FROM MOVABLE_CALCULATION_PLAN R 
CONNECT BY R.OID = PRIOR R.CALCULATION_PLAN_PARENT_OID 
START WITH R.RELATED_YEAR = 2015 
    AND REGEXP_LIKE (R.CALCULATION_PLAN_NAME,'ROL') 
    AND R.CALCULATION_PLAN_PARENT_OID != 0 
    /*Following condition is replacement for CONNECT_BY_ISLEAF = 1, 
    Since you're connecting in reverse you can't use it*/ 
    AND not exists 
    (select 'x' from MOVABLE_CALCULATION_PLAN R2 
    where R2.CALCULATION_PLAN_PARENT_OID = R.OID) 
) 

select SUBSTR(SYS_CONNECT_BY_PATH(Q.CALCULATION_PLAN_CODE, '.'),2) CODE_PATH, 
     SUBSTR(SYS_CONNECT_BY_PATH(Q.CALCULATION_PLAN_NAME, ' > '),4) NAME_PATH 
    from Q 
    CONNECT BY PRIOR Q.OID = Q.CALCULATION_PLAN_PARENT_OID 
    and prior Q.leafid = leafid 
    START WITH NVL(CALCULATION_PLAN_PARENT_OID, 0) = 0 

像往常一樣通過查詢連接,性能可能是一個問題,但是從我對類似的表結構,看到它仍然是相當快的。另請參見http://sqlfiddle.com/#!4/dd5b68/6

P.S.在將來,一定要向我們提供樣本數據和對您的條件的恰當描述,不要讓我們破譯您的查詢並自己想想樣本。

相關問題