2013-07-02 82 views
1

我有一個使用connect by語句來排序遞歸數據的查詢。我遇到的問題是偶爾會有一對多或多對一的關係,我不知道如何處理它。PLSQL - 以前連接(多對多)

SELECT * 
FROM (SELECT * FROM bdTable WHERE parentek = t_parKey) 
START WITH source is null 
CONNECT BY PRIOR target = source 

這樣解釋。我有一個源和目標列。大約99%的時間是一個唯一的ID。不幸的是,另外1%的時間裏有一列中的ID分組。該表是流程圖類型工具的平面表示,因此可以有許多輸出和合並的分割和決策,這些輸入和合並可以有很多輸入。

要在加載表的數據時處理此問題,使用listagg函數將唯一ID連接在一起。所以我最終得到了一個像'1254143,2356334,6346436,3454363,3462354,442356'這樣的目標值。

所以當我通過連接語句執行時,它完美的工作,直到它涉及到這些場景之一,在這一點上它剛剛停止(這當然是預期的)。
我想我可能能夠以某種方式使用IN或INSTR來使其工作,但還沒有運氣,我在網上找不到任何東西。

任何幫助,將不勝感激.....

+0

你能提供某種模式嗎?此外,串聯的「唯一」ID一般不是最佳策略,您可能想要創建自己的唯一ID。 – dougEfresh

+0

雖然我沒有看到創建自己的唯一ID作爲答案,但它確實讓我想到了一個可能的解決方案。現在就讓我和我一起。不管怎麼說,還是要謝謝你。 – user2542663

回答

0

如果你想加入targetsource與使用的一些邏輯的基礎上,設定值的交集,每一列中列出,則最可靠的方法這樣做是將字符串拆分爲集合,並對前一行的集合和當前行的集合進行操作以構建樹。

有許多技術可以從Oracle中的分隔字符串中構建集合,其中一個示例爲in this answer to another question

創建所需的集合類型:

create or replace type TIdList as table of varchar2(100); 

內你的情況選擇應該是這樣的:

SELECT 
    t.*, 
    (
    cast(multiset(-- Convert set of values into collection 
     select -- Build list of values from separated string 
      substr(
      source, 
      decode(level, 1, 1, instr(source,',',1,level-1)+1), 
      decode(instr(source,',',1,level), 0, length(source)+1, instr(source,',',1,level)) 
       - 
       decode(level, 1, 1, instr(source,',',1,level-1)+1) 
     ) code 
     from dual 
     start with source is not null 
     connect by instr(source,',',1,level-1) > 0 

    ) as TIdList) 
)       source_id_list, 
    (
    cast(multiset(-- Convert set of values into collection 
     select -- Build list of values from separated string 
      substr(
      target, 
      decode(level, 1, 1, instr(target,',',1,level-1)+1), 
      decode(instr(target,',',1,level), 0, length(target)+1, instr(target,',',1,level)) 
       - 
       decode(level, 1, 1, instr(target,',',1,level-1)+1) 
     ) code 
     from dual 
     start with target is not null 
     connect by instr(target,',',1,level-1) > 0 
    ) as TIdList) 
)       target_id_list 
FROM bdTable t 
WHERE t.parentek = t_parKey 

因爲我不知道哪個列(sourcetarget)包含分隔的列表,我包括每個列。

建立集合後,可以使用multiset operators和可用的test functions來將目標與源相匹配。例如。

with inner_query as (
    SELECT 
    t.*, 
    (
     cast(multiset(-- Convert set of values into collection 
     select -- Build list of values from separated string 
      substr(
       source, 
       decode(level, 1, 1, instr(source,',',1,level-1)+1), 
       decode(instr(source,',',1,level), 0, length(source)+1, instr(source,',',1,level)) 
       - 
       decode(level, 1, 1, instr(source,',',1,level-1)+1) 
      ) code 
     from dual 
     start with source is not null 
     connect by instr(source,',',1,level-1) > 0 

    ) as TIdList) 
    )       source_id_list, 
    (
     cast(multiset(-- Convert set of values into collection 
     select -- Build list of values from separated string 
      substr(
       target, 
       decode(level, 1, 1, instr(target,',',1,level-1)+1), 
       decode(instr(target,',',1,level), 0, length(target)+1, instr(target,',',1,level)) 
       - 
       decode(level, 1, 1, instr(target,',',1,level-1)+1) 
      ) code 
     from dual 
     start with target is not null 
     connect by instr(target,',',1,level-1) > 0 
    ) as TIdList) 
    )       target_id_list 
    FROM bdTable t 
    WHERE t.parentek = t_parKey 
) 
select 
    level  lvl, 
    tree_list.* 
from 
    inner_query tree_list 
start with 
    source is null 
connect by 
    nvl(cardinality(prior target_id_list MULTISET INTERSECT source_id_list),0) > 0 

如果只有一個列可以包含的值列表,然後MEMBER OF構建體是有用的。