Sql Oracle中的简单递归查询

Sql Oracle中的简单递归查询,sql,oracle,recursive-query,Sql,Oracle,Recursive Query,我目前在理解和编写递归查询方面遇到了一些困难。我知道递归查询用于搜索信息的层次结构,但我还没有在网上找到一个简单的解决方案,可以沿着层次结构进行搜索。例如,假设我有一个关系,它模拟了一个族谱: create table family_tree ( child varchar(10) parent varchar(10) ); 如果我想写一个递归查询,沿着这个家族树,收集所有的父母,直到原点,我应该怎么做呢 提前感谢。您可以使用连接方式子句 在您的情况下,SQL可能如下所示: select ch

我目前在理解和编写递归查询方面遇到了一些困难。我知道递归查询用于搜索信息的层次结构,但我还没有在网上找到一个简单的解决方案,可以沿着层次结构进行搜索。例如,假设我有一个关系,它模拟了一个族谱:

create table family_tree (
child varchar(10)
parent varchar(10)
);
如果我想写一个递归查询,沿着这个家族树,收集所有的父母,直到原点,我应该怎么做呢


提前感谢。

您可以使用
连接方式
子句

在您的情况下,SQL可能如下所示:

select child, parent, level
from family_tree 
connect by prior parent = child

您熟悉
SCOTT.EMP
表吗?它位于“standard”
SCOTT
模式中(不幸的是,自12.1版左右以来,该模式不再与Oracle数据库的每个副本预先打包)。检查你的数据库:你可以在那里找到它。或者询问您的DBA

无论如何:该表显示了一家小型企业的14名员工,其中包括员工ID以及他或她的经理的员工ID。因此,假设您从某个员工开始,并希望找到他或她的最高级别的老板。(与您的测试问题类似)在这个特定的层次结构中,最高级别的“祖先”是唯一的,但这是不相关的;如果每个部门都有一个“部门负责人”,并且部门负责人之上没有首席执行官,则递归查询的工作方式相同

在这种安排下,很容易识别“所有老板中的老板”——他没有老板。在他的行中,经理ID为
null
。对于树状层次结构的“根”(或“根”),这是一种非常常见的安排

下面是你如何找到老板的,从一个特定的员工id开始,使用递归查询——据我所知,这是你想要练习的。(也就是说:如果我理解正确,您对“通过任何方式”解决问题都不感兴趣;相反,您希望在一个小示例中看到递归查询是如何工作的,这样您就可以理解所有发生的事情。)

我不会试图猜测你在理解这个例子时会遇到什么困难。相反,我会等你问

如果我想写一个递归查询,沿着这个家族树,收集所有的父母,直到原点,我应该怎么做呢

使用分层查询和
SYS\u CONNECT\u BY\u PATH(列名,分隔符)
函数:

Oracle 18安装程序

create table family_tree (
  child varchar(10),
  parent varchar(10)
);

INSERT INTO family_tree ( child, parent )
  SELECT 'B', 'A' FROM DUAL UNION ALL
  SELECT 'C', 'B' FROM DUAL UNION ALL
  SELECT 'D', 'C' FROM DUAL UNION ALL
  SELECT 'E', 'D' FROM DUAL UNION ALL
  SELECT 'F', 'C' FROM DUAL;
SELECT SYS_CONNECT_BY_PATH( parent, ' -> ' ) || ' -> ' || child AS path
FROM   family_tree
START WITH parent = 'A'
CONNECT BY PRIOR child = parent;
PATH
-------------------------
 -> A -> B
 -> A -> B -> C
 -> A -> B -> C -> D
 -> A -> B -> C -> D -> E
 -> A -> B -> C -> F
查询1

create table family_tree (
  child varchar(10),
  parent varchar(10)
);

INSERT INTO family_tree ( child, parent )
  SELECT 'B', 'A' FROM DUAL UNION ALL
  SELECT 'C', 'B' FROM DUAL UNION ALL
  SELECT 'D', 'C' FROM DUAL UNION ALL
  SELECT 'E', 'D' FROM DUAL UNION ALL
  SELECT 'F', 'C' FROM DUAL;
SELECT SYS_CONNECT_BY_PATH( parent, ' -> ' ) || ' -> ' || child AS path
FROM   family_tree
START WITH parent = 'A'
CONNECT BY PRIOR child = parent;
PATH
-------------------------
 -> A -> B
 -> A -> B -> C
 -> A -> B -> C -> D
 -> A -> B -> C -> D -> E
 -> A -> B -> C -> F
结果

create table family_tree (
  child varchar(10),
  parent varchar(10)
);

INSERT INTO family_tree ( child, parent )
  SELECT 'B', 'A' FROM DUAL UNION ALL
  SELECT 'C', 'B' FROM DUAL UNION ALL
  SELECT 'D', 'C' FROM DUAL UNION ALL
  SELECT 'E', 'D' FROM DUAL UNION ALL
  SELECT 'F', 'C' FROM DUAL;
SELECT SYS_CONNECT_BY_PATH( parent, ' -> ' ) || ' -> ' || child AS path
FROM   family_tree
START WITH parent = 'A'
CONNECT BY PRIOR child = parent;
PATH
-------------------------
 -> A -> B
 -> A -> B -> C
 -> A -> B -> C -> D
 -> A -> B -> C -> D -> E
 -> A -> B -> C -> F

有一种我并不十分熟悉的ANSI语法,还有一种我通常使用的Oracle语法。Oracle语法使用
connectby。。。PRIOR
子句来构建树,还有一个
START WITH
子句告诉数据库从何处开始遍历树。它将如下所示:

SELECT child, parent, level
  FROM family_tree
CONNECT BY ...
START WITH ...
START WITH
子句更简单。你在“向上”看树,所以你会在你想开始在树上行走的地方挑选一个孩子。所以这看起来像是
从parent='John'
开始。这是我们的一级排。我假设约翰的那一排将有他作为父母,没有孩子,因为这是树的底部

现在,想想树中的行是如何相互关联的。如果我们看的是2级行,我们如何知道它是否是“John”行的正确行?在本例中,子列中将包含John。所以我们需要一个子句:
connectbypreviousparent=child
。这意味着“前一行的父项等于此行的子项”

因此,查询如下所示:

SELECT child, parent, level
  FROM family_tree
CONNECT BY PRIOR parent = child
START WITH parent = 'John'


(这是一个有点奇怪的例子,因为实际的孩子有双亲,但这会使事情变得更复杂。)

我的理解是OP不想以任何方式解决“婴儿问题”。相反,他正在学习递归WITH子句,并希望通过一些小例子来了解它是如何工作的。如果这是正确的,那么“按连接”解决方案将无济于事。