2017-09-15 47 views
0

我使用一个表中的应用程序建模的多级菜单,返回过滤行和其所有祖先:甲骨文子查询重构是如何

CREATE TABLE 
    CWE_MENUS 
    (
     NODE_ID INTEGER NOT NULL, 
     PARENT_NODE INTEGER, 
     INLINE_SORT_NO INTEGER NOT NULL, 
     ICON VARCHAR2(32), 
     TEXT VARCHAR2(32) NOT NULL, 
     ACTION_TYPE VARCHAR2(32), 
     ACTION_INFO VARCHAR2(512), 
     ENABLED CHAR(1), 
     REMARK VARCHAR2(128), 
     PRIMARY KEY (NODE_ID), 
     CONSTRAINT CWE_MENUS_FK1 FOREIGN KEY (PARENT_NODE) REFERENCES "CWE_MENUS" ("NODE_ID") 
    ); 

而且使用我这样的SQL获取所有菜单数据:

select T.*, case when exists(select node_id from cwe_menus D where D.parent_node=T.node_id) then 0 else 1 end as leaf from (
    WITH link(NODE_ID, PARENT_NODE, INLINE_SORT_NO, ICON, TEXT, ACTION_TYPE, ACTION_INFO, ENABLED, REMARK, lvl,pth) AS (
     SELECT NODE_ID, PARENT_NODE, INLINE_SORT_NO, ICON, TEXT, ACTION_TYPE, ACTION_INFO, ENABLED, REMARK, 1 as lvl, ''||node_id as pth 
     FROM cwe_menus 
     where parent_node is null 
     UNION ALL 
     SELECT p2.NODE_ID, p2.PARENT_NODE, p2.INLINE_SORT_NO, p2.ICON, p2.TEXT, p2.ACTION_TYPE, p2.ACTION_INFO, p2.ENABLED, p2.REMARK, p1.lvl + 1 as lvl, p1.pth||'.'||p2.node_id as pth 
     FROM link p1 INNER JOIN cwe_menus p2 ON p1.node_id = p2.parent_node 
    ) 
    SEARCH DEPTH FIRST BY INLINE_SORT_NO SET order1 
    SELECT distinct * FROM link ORDER BY order1 
) T 

这工作像一个魔术,但我怎么能应用一些条件来过滤数据,同时保持树结构?我的意思是返回所有匹配的行和它们的祖先行。我还需要按照INLINE_SORT_NO排序的所有兄弟,我还需要LVL, PATH, LEAF列。

我已经检查了oracle文档和网上的一些教程,但他们都没有提到如何做到这一点,并为我可怜的英语感到抱歉。

回答

0

只需使用hierarchical queries -

SELECT v.*, connect_by_isleaf as LEAF, level as LVL, sys_connect_by_path(text,'.') as PATH 
FROM 
    (
     SELECT s.* 
     FROM cwe_menus s 
    CONNECT BY PRIOR parent_node = node_id 
     START WITH (text = 3) /* filter condition*/ 
    ) v 
CONNECT BY PRIOR node_id = parent_node 
START WITH parent_node IS NULL 
ORDER SIBLINGS BY inline_sort_no