2013-03-24 60 views
2

我想在叶级别上使用条件执行分级查询。具有叶级别条件的Oracle递归分层查询

我想查询过滤所有父 - 子关系,其中叶级statisfies条件:ID LIKE '3%'

表t是:

ParentId,Id 
INSERT INTO t VALUES ('VTE', 'VTP'); 
INSERT INTO t VALUES ('VTP', '202'); 
INSERT INTO t VALUES ('SER', '606'); 
INSERT INTO t VALUES ('SER', '609'); 
INSERT INTO t VALUES ('GIF', '301'); 
INSERT INTO t VALUES ('ECH', '302'); 
INSERT INTO t VALUES ('PUB', 'MER'); 
INSERT INTO t VALUES ('MER', '312'); 
INSERT INTO t VALUES ('MER', '313'); 
INSERT INTO t VALUES ('MER', '314'); 
INSERT INTO t VALUES ('MES', '318'); 
INSERT INTO t VALUES ('PUB', 'PRE'); 
INSERT INTO t VALUES ('PUB', 'PAP'); 
INSERT INTO t VALUES ('STA', '317'); 
INSERT INTO t VALUES ('NIV', 'ANS'); 
INSERT INTO t VALUES ('ZNM', '497'); 
INSERT INTO t VALUES ('ZNU', '496'); 
INSERT INTO t VALUES ('ANS', 'ZNC'); 
INSERT INTO t VALUES ('ZNC', '491'); 
INSERT INTO t VALUES ('NUL', 'NIV'); 
INSERT INTO t VALUES ('NIV', 'VTE'); 
INSERT INTO t VALUES ('VTE', 'VTC'); 
INSERT INTO t VALUES ('VTC', '100'); 
INSERT INTO t VALUES ('VTP', '204'); 
INSERT INTO t VALUES ('VTP', '205'); 
INSERT INTO t VALUES ('VTA', '500'); 
INSERT INTO t VALUES ('SER', '600'); 
INSERT INTO t VALUES ('NIV', 'PUB'); 
INSERT INTO t VALUES ('ECH', '303'); 
INSERT INTO t VALUES ('MER', '305'); 
INSERT INTO t VALUES ('MER', '306'); 
INSERT INTO t VALUES ('MER', '309'); 
INSERT INTO t VALUES ('PAP', '605'); 
INSERT INTO t VALUES ('SEP', 'PBC'); 
INSERT INTO t VALUES ('PBC', '601'); 
INSERT INTO t VALUES ('SEP', 'STA'); 
INSERT INTO t VALUES ('NIV', 'TRA'); 
INSERT INTO t VALUES ('ZNP', '498'); 
INSERT INTO t VALUES ('ANS', 'ZNM'); 
INSERT INTO t VALUES ('ANS', 'ZNE'); 
INSERT INTO t VALUES ('ANS', 'ZNR'); 
INSERT INTO t VALUES ('ZNR', '493'); 
INSERT INTO t VALUES ('ZNF', '492'); 
INSERT INTO t VALUES ('VTC', '101'); 
INSERT INTO t VALUES ('VTC', '102'); 
INSERT INTO t VALUES ('VTE', 'VTA'); 
INSERT INTO t VALUES ('VTE', 'SER'); 
INSERT INTO t VALUES ('AUT', '900'); 
INSERT INTO t VALUES ('PUB', 'CPR'); 
INSERT INTO t VALUES ('MER', '310'); 
INSERT INTO t VALUES ('MER', '311'); 
INSERT INTO t VALUES ('MER', '604'); 
INSERT INTO t VALUES ('PUB', 'MES'); 
INSERT INTO t VALUES ('MES', '316'); 
INSERT INTO t VALUES ('SEP', 'RSF'); 
INSERT INTO t VALUES ('RSF', '608'); 
INSERT INTO t VALUES ('TRA', 'TRP'); 
INSERT INTO t VALUES ('TRP', '603'); 
INSERT INTO t VALUES ('ANS', 'ZNP'); 
INSERT INTO t VALUES ('ANS', 'ZNU'); 
INSERT INTO t VALUES ('ANS', 'ZNG'); 
INSERT INTO t VALUES ('ANS', 'ZNF'); 
INSERT INTO t VALUES ('VTC', '104'); 
INSERT INTO t VALUES ('VTC', '105'); 
INSERT INTO t VALUES ('VTP', '200'); 
INSERT INTO t VALUES ('VTP', '201'); 
INSERT INTO t VALUES ('VTP', '203'); 
INSERT INTO t VALUES ('VTA', '400'); 
INSERT INTO t VALUES ('VTE', 'AUT'); 
INSERT INTO t VALUES ('CPR', '602'); 
INSERT INTO t VALUES ('PUB', 'GIF'); 
INSERT INTO t VALUES ('PUB', 'ECH'); 
INSERT INTO t VALUES ('MER', '307'); 
INSERT INTO t VALUES ('MER', '308'); 
INSERT INTO t VALUES ('PRE', '304'); 
INSERT INTO t VALUES ('PRE', '315'); 
INSERT INTO t VALUES ('NIV', 'SEP'); 
INSERT INTO t VALUES ('TRP', '607'); 
INSERT INTO t VALUES ('ANS', 'ZNA'); 
INSERT INTO t VALUES ('ZNA', '499'); 
INSERT INTO t VALUES ('ZNG', '495'); 
INSERT INTO t VALUES ('ZNE', '494'); 
COMMIT; 

我initialy想我可以使用类似:

SELECT ParentId, Id 
FROM t 
WHERE id LIKE '3%' 
start with ParentId ='NIV' 
CONNECT BY PRIOR Id = ParentId 

例如, 302的父亲是ECH ECH的父亲是PUB PUB的父亲是NIV

但查询只显示级别0的关系: 302的父亲是ECH

它丢弃所有的更高水平的根: ECH的父亲是PUB PUB的父亲是NIV

我想出了下面的解决方案。

但是,孩子父母循环是硬编码的,这会破坏分层查询的目的,其中自动识别子父母关系的数量。

SELECT parentid, id 
FROM t 
WHERE id IN 
    (SELECT parentid 
    FROM t 
    WHERE 
    id IN 
    (SELECT parentid 
     FROM t 
     WHERE id LIKE '3%' 
     start with parentid='NIV' 
     CONNECT BY PRIOR id = parentid) 
     start with parentid ='NIV' 
     CONNECT BY PRIOR id = parentid) 
OR 
ccomuse IN 
    (SELECT parentid 
    FROM t 
    WHERE id LIKE '3%' 
    start with parentid ='NIV' 
    CONNECT BY PRIOR id = parentid) 
OR 
id LIKE '3%' 
start with parentid ='NIV' 
CONNECT BY PRIOR id = parentid 

有没有一种方法来提取所有的孩子 - 父母关系,而不用硬编码2内部循环,即用自动到达根的递归方法?

回答

0

尝试从错误的一端搭树:-)

SELECT distinct ParentId, Id 
FROM t 
start with Id LIKE '3%' 
CONNECT BY Id = prior ParentId and Id <> 'NIV' 

fiddle

0

如果要过滤所有的父亲 - 子关系,其中叶级满足条件,那么您需要在connect by子句中指定条件。它将消除不必要的节点,并从输出中删除它的子节点。如果在where子句中指定条件,则子节点将在没有父节点的情况下显示,因此输出将不会有意义。