Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/oracle/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 如何编写不添加已访问值的递归查询?_Sql_Oracle_Recursive Query - Fatal编程技术网

Sql 如何编写不添加已访问值的递归查询?

Sql 如何编写不添加已访问值的递归查询?,sql,oracle,recursive-query,Sql,Oracle,Recursive Query,让我们假设任何给定的客户机都可以有多个框。每个框可以包含多个项目以及多个框(子框) 不幸的是,由于业务规则,可能会创建一个循环 BoxA -> Item1, BoxB, BoxC BoxB -> BoxA, BoxD 如您所见,BoxA包含BoxB,而BoxB包含BoxA 我试图解决的问题是获取客户端中给定框列表的所有子框。 因此,如果我正在寻找BoxA的子框(来自上一个示例),我将得到以下内容:BoxB、BoxC、BoxA、BoxD 这就是我到目前为止所做的: WITH bo

让我们假设任何给定的客户机都可以有多个框。每个框可以包含多个项目以及多个框(子框)

不幸的是,由于业务规则,可能会创建一个循环

BoxA -> Item1, BoxB, BoxC  
BoxB -> BoxA, BoxD
如您所见,BoxA包含BoxB,而BoxB包含BoxA

我试图解决的问题是获取客户端中给定框列表的所有子框。

因此,如果我正在寻找BoxA的子框(来自上一个示例),我将得到以下内容:BoxB、BoxC、BoxA、BoxD

这就是我到目前为止所做的:

WITH box_info AS (
    -- This is typically a bit more complicated, that's why I have it in a seperate WITH clause
    SELECT sub_box_id
    FROM client_box
    WHERE box_id = 1
),
all_sub_boxes(sub_box_id) AS (
    SELECT sub_box_id
    FROM box_info
    WHERE sub_box_id IS NOT NULL

    UNION ALL

    SELECT cb.sub_box_id
    FROM client_box cb, all_sub_boxes asb
    WHERE cb.box_id = asb.sub_box_id AND cb.sub_box_id IS NOT NULL
    -- AND cb.sub_box_id NOT IN (SELECT sub_box_id FROM all_sub_boxes)
)
SELECT sub_box_id FROM all_sub_boxes;
但是,由于有可能陷入递归循环,WITH子句的“all_sub_BOX”将失败。注释掉的行是我直观地放进去的,因为它防止已经访问过的子框被添加到递归列表中,但是我们似乎不能从内部引用“所有子框”

因此,本质上,我需要一种在递归查询中不包含已经包含的子框的方法。
也许我可以创建一个临时表?但我甚至不知道在递归查询期间是否可以插入到表中。另外,如果每次都创建临时表,那么每次运行此查询的成本是多少

我正在尝试编写这个查询,以便它可以跨不同的商业数据库使用,所以如果我可以避免使用非标准sql,那就太好了。但我明白,如果不可能,那就是事实

编辑 为清晰起见,以下是
客户机\u框
表的外观:

+--------+---------+------------+
| BOX_ID | ITEM_ID | SUB_BOX_ID |
+--------+---------+------------+
| BoxA   | Item1   | (null)     |
| BoxA   | (null)  | BoxB       |
| BoxA   | (null)  | BoxC       |
| BoxB   | (null)  | BoxA       |
| BoxB   | (null)  | BoxD       |
+--------+---------+------------+

你在正确的轨道上,你似乎只是需要一点帮助来处理周期。请参阅递归CTE定义末尾的CYCLE子句(即使CYCLE子句位于递归CTE的右括号之后,它仍然是它的一部分):


“我在寻找BoxA的子框”推断BoxA位于层次结构树中任何“子框”的上方(父级)。所以你应该返回B,C,D子框(儿童),我想。无论如何,听起来您需要一个分层树查询(可能是nocycle)。寻找more@tbone是的,这是准确的。“连接方式”是oracle特有的关键字,对吗?有没有一种方法可以不用特定于Oracle的东西来编写这个查询?恕我直言,但我始终不理解这样一个想法,即您必须不惜一切代价争取通用的香草味SQL。我假设您的公司正在为Oracle许可证付费(基于您的问题Oracle标签),所以请使用您已经付费的工具。可能会有涉及多层连接的黑客攻击,或者复杂(可能有缺陷)的过程代码,但是如果您的数据库提供现成的解决方案,我会首先使用它。也就是说,我相信其他主要数据库支持或将支持分层查询的概念(例如)@我问这个问题的唯一原因是因为我们可能要离开甲骨文了。这就是为什么我想看看这是否可能,因为我不想经历翻译的头痛。但正如我所说的,如果不可能,那没关系,我只使用CONNECT BY子句。非常感谢您发布这篇文章。然而,我试图找到更多关于CYCLE关键字的信息,但没有任何明确的信息。我可能只是找错地方了。你能给我提供更多的信息或给我指出正确的文档吗?还有,这是Oracle特有的关键字吗?@gjvatsalya-看看这是否有用。另外,看看PostgreSQL现在是否有类似于cycle子句的内容,它似乎在八年前没有。
+--------+---------+------------+
| BOX_ID | ITEM_ID | SUB_BOX_ID |
+--------+---------+------------+
| BoxA   | Item1   | (null)     |
| BoxA   | (null)  | BoxB       |
| BoxA   | (null)  | BoxC       |
| BoxB   | (null)  | BoxA       |
| BoxB   | (null)  | BoxD       |
+--------+---------+------------+
with
-- Begin simulated data.
  client_box ( box_id, item_id, sub_box_id ) as (
    select 'BoxA', 'Item1', null   from dual union all
    select 'BoxA', null   , 'BoxB' from dual union all
    select 'BoxA', null   , 'BoxC' from dual union all
    select 'BoxB', null   , 'BoxA' from dual union all
    select 'BoxB', null   , 'BoxD' from dual
  ),
-- End of simulated data (for testing only, not part of the solution).
-- SQL query consists of the keyword WITH (above) and the lines below.
-- Use your actual table and column names.
-- Use whatever mechanism works for you in the ANCHOR branch of r (below).
  r ( box_id ) as (
    select  'BoxA' from dual   --  Modify this for inputs
    union all
    select  c.sub_box_id
      from  client_box c join r on c.box_id = r.box_id
      where c.sub_box_id is not null
  )
  cycle box_id set cycle to 1 default 0
select box_id
from   r
where  cycle = 0
;

BOX_ID
------
BoxA
BoxB
BoxC
BoxD