【问题标题】:SQL query for searching in the tree在树中搜索的 SQL 查询
【发布时间】:2014-02-17 15:38:08
【问题描述】:

我有一个包含 4 级深度数据的简单树。这是 DDL 表

CREATE TABLE HIER_DEMO(
   ID        NUMBER,
   LABEL     VARCHAR2 (100),
   PARENT_ID NUMBER)

层次结构从WITH ID = PARENT_ID 开始。级别数是固定的。它总是 4。我们在第 4 级的所有分支上都有叶子。因此,如果需要,我们还可以再添加 3 列代表祖先的 LABEL。

我需要构建一个查询

  1. 在任何层次结构级别的 LABEL 中搜索特定短语。例如LABEL LIKE '%MAGIC_WORD%'
  2. 返回层次结构节点下满足条件 1 的所有节点直到叶级。
  3. 此外,我们需要返回满足条件 1 的层次结构节点的所有祖先。

这是一个例子

INSERT INTO HIER_DEMO VALUES (1, 'Mike', 1);
INSERT INTO HIER_DEMO VALUES (2, 'Arthur', 2);
INSERT INTO HIER_DEMO VALUES (3, 'Alex', 1);
INSERT INTO HIER_DEMO VALUES (4, 'Suzanne', 1);
INSERT INTO HIER_DEMO VALUES (5, 'Brian', 3);
INSERT INTO HIER_DEMO VALUES (6, 'Rick', 3);
INSERT INTO HIER_DEMO VALUES (7, 'Patrick', 4);
INSERT INTO HIER_DEMO VALUES (8, 'Simone', 4);
INSERT INTO HIER_DEMO VALUES (9, 'Tim', 5);
INSERT INTO HIER_DEMO VALUES (10, 'Andrew', 5);
INSERT INTO HIER_DEMO VALUES (11, 'Sandy', 6);
INSERT INTO HIER_DEMO VALUES (12, 'Brian', 6);
INSERT INTO HIER_DEMO VALUES (13, 'Chris', 7);
INSERT INTO HIER_DEMO VALUES (14, 'Laure', 7);
INSERT INTO HIER_DEMO VALUES (15, 'Maureen', 8);
INSERT INTO HIER_DEMO VALUES (16, 'Andy', 8);
INSERT INTO HIER_DEMO VALUES (17, 'Al', 2);
INSERT INTO HIER_DEMO VALUES (18, 'John', 17);
INSERT INTO HIER_DEMO VALUES (19, 'Frank', 18);
INSERT INTO HIER_DEMO VALUES (20, 'Tim', 19);

我正在寻找在 LABEL 列中搜索“Brian”树的查询

查询应该返回这些数据

ID  LABEL   PARENT_ID
1   Mike    1
3   Alex    1
5   Brian   3
6   Rick    3
9   Tim 5
10  Andrew  5
12  Brian   6

有人可以帮助处理 Oracle 查询吗?我们使用的是 11.2 版本的 Oracle 数据库。

【问题讨论】:

    标签: sql oracle search tree


    【解决方案1】:
    SQL> select * from HIER_DEMO
      2  start with label like '%Brian%'
      3  connect by prior id = parent_id
      4  union
      5  select * from HIER_DEMO
      6  start with label like '%Brian%'
      7  connect by prior parent_id = id and PRIOR parent_id != PRIOR id
      8  /
    
      ID LABEL                PARENT_ID                                             
    ---- -------------------- ---------                                             
       1 Mike                         1                                             
       3 Alex                         1                                             
       5 Brian                        3                                             
       6 Rick                         3                                             
       9 Tim                          5                                             
      10 Andrew                       5                                             
      12 Brian                        6    
    

    【讨论】:

    • 不适用于'%Mike%' 而不是'%Brian%'
    • 叶戈尔,有趣。我添加了 nocycle,它现在也适用于“Make”。
    【解决方案2】:

    我们可以使用递归 CTE 来完成此操作

    WITH CTE1(ID, LABEL,PARENT_ID) AS
    (
        SELECT * FROM Hier_Demo 
        WHERE LABEL LIKE '%Brian%' 
        UNION ALL
        SELECT h.ID, h.LABEL, h.PARENT_ID FROM Hier_Demo h
        INNER JOIN CTE1 c
        ON h.ID = c.PARENT_ID
        WHERE h.ID <> h.PARENT_ID   
    ),
    CTE2(ID, LABEL,PARENT_ID) AS
    (
        SELECT * FROM Hier_Demo 
        WHERE LABEL LIKE '%Brian%' 
        UNION ALL
        SELECT h.ID, h.LABEL, h.PARENT_ID FROM Hier_Demo h
        INNER JOIN CTE2 c
        ON h.PARENT_ID = c.ID  
    )
    SELECT  * FROM CTE2
    UNION 
    SELECT  * FROM CTE1 
    UNION 
    SELECT * FROM HIER_DEMO WHERE ID = 1
    

    在上面的代码中,CTE1 在层次结构中向上获取记录,CTE2 在 Brian 的层次结构中向下获取记录,之后我们只需 UNION 这些 CTE 返回的记录

    查看在 SQLFiddle 工作的代码:http://sqlfiddle.com/#!4/0c99d/39

    【讨论】:

    • 我正在处理一个错误,ID = 1 的记录没有显示在输出中
    • 在我想不出更好的东西后添加了SELECT * FROM HIER_DEMO WHERE ID = 1
    • 这棵树总是会返回至少一条记录。而如果它没有找到任何东西,它不应该返回任何东西。 :)
    • 不用担心 Dipendu,Dmitry 已经提供了正确答案。
    【解决方案3】:

    你可以试试这个:

        SELECT * FROM HIER_DEMO WHERE PARENT_ID=
        (SELECT id FROM HIER_DEMO WHERE LABEL='Brian');
    

    【讨论】:

    • 先生,感谢您的快速回复。您介意先尝试自己运行查询,然后再将其发布到此处吗?谢谢。我确信这是不正确的查询。不过还是谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多