执行递归查询时检测到循环

Cycle detected while executing recursive query

我正在使用 CTE 递归查询来获得低于输出但不知道为什么会这样 抛出“执行递归 WITH 查询时检测到的循环”。谁能告诉我我的查询哪里出了问题?

我的查询:

WITH
cte (order_id,
     product_id,
     quantity,
     cnt)
AS
    (SELECT order_id,
            product_id,
            1 as quantity,
            1 as cnt
       FROM order_tbl2        
     UNION ALL
     SELECT a.order_id,
            a.product_id,
            b.quantity,
            b.cnt + 1
       FROM order_tbl2 A INNER JOIN cte b ON a.product_id = b.product_id
      WHERE  b.cnt + 1 < a.quantity)

SELECT order_id, product_id, 数量 来自 cte;

table/data 脚本:

CREATE TABLE ORDER_TBL2
(
ORDER_PAY   DATE,
ORDER_ID    VARCHAR2(10 BYTE),
PRODUCT_ID  VARCHAR2(10 BYTE),
QUANTITY    NUMBER(5),
PRICE       NUMBER(5)
);

Insert into ORDER_TBL2
 (ORDER_PAY, ORDER_ID, PRODUCT_ID, QUANTITY, PRICE)
Values
 (TO_DATE('5/1/2015', 'MM/DD/YYYY'), 'ORD1', 'PROD1', 5, 5);
Insert into ORDER_TBL2
 (ORDER_PAY, ORDER_ID, PRODUCT_ID, QUANTITY, PRICE)
Values
 (TO_DATE('5/1/2015', 'MM/DD/YYYY'), 'ORD2', 'PROD2', 2, 10);
Insert into ORDER_TBL2
 (ORDER_PAY, ORDER_ID, PRODUCT_ID, QUANTITY, PRICE)
Values
 (TO_DATE('5/1/2015', 'MM/DD/YYYY'), 'ORD3', 'PROD3', 3, 25);

COMMIT;

我认为您正在尝试扩展行。如果是这样,则不需要 join

WITH cte (order_id, product_id, quantity, cnt) AS (
      SELECT order_id, product_id, quantity, 1 as cnt
      FROM order_tbl2        
      UNION ALL
      SELECT order_id, product_id, quantity, cnt + 1
      FROM cte
      WHERE cnt < a.quantity
     )
SELECT *
FROM cte;

在递归成员中,您目前仅在 a.product_id = b.product_id 而不是 a.order_id = b.order_id AND a.product_id = b.product_id 加入;这在这里并不直接重要,但如果不同的订单包含相同的产品,这在现实世界中很可能会发生。

您的数据和查询实际上似乎没有循环。您似乎被 ANSI 连接的错误绊倒了;添加 cycle 子句不会像预期的那样显示任何循环行 - 并使其起作用!;它适用于旧式连接:

WITH
    cte (order_id,
         product_id,
         quantity,
         cnt)
    AS
        (SELECT order_id,
                product_id,
                1 as quantity,
                1 as cnt
           FROM order_tbl2        
         UNION ALL
         SELECT a.order_id,
                a.product_id,
                b.quantity,
                b.cnt + 1
           FROM order_tbl2 A, cte b
          WHERE b.cnt + 1 < a.quantity
            AND a.order_id = b.order_id
            AND a.product_id = b.product_id
            )
SELECT order_id, product_id, quantity
  FROM cte;

db<>fiddle

虽然您根本不需要加入;你可以这样做:

WITH
    cte (order_id,
         product_id,
         quantity,
         cnt)
    AS
        (SELECT order_id,
                product_id,
                quantity,
                1 as cnt
           FROM order_tbl2        
         UNION ALL
         SELECT b.order_id,
                b.product_id,
                b.quantity,
                b.cnt + 1
           FROM cte b
          WHERE  b.cnt < b.quantity)
SELECT order_id, product_id, 1 as quantity
  FROM cte;

在最后select中分配固定的1个数量,或者:

WITH
    cte (order_id,
         product_id,
         real_quantity,
         quantity,
         cnt)
    AS
        (SELECT order_id,
                product_id,
                quantity as real_quantity,
                1 as quantity,
                1 as cnt
           FROM order_tbl2        
         UNION ALL
         SELECT b.order_id,
                b.product_id,
                b.real_quantity,
                b.quantity,
                b.cnt + 1
           FROM cte b
          WHERE  b.cnt < b.real_quantity)
SELECT order_id, product_id, quantity
  FROM cte;

在里面赋值,需要跟踪原始数量作为新的别名。

对于这两个,我都从数量比较中删除了 + 1,因为那会使它停止得太早;添加 order by,他们都得到:

ORDER_ID PRODUCT_ID QUANTITY
ORD1 PROD1 1
ORD1 PROD1 1
ORD1 PROD1 1
ORD1 PROD1 1
ORD1 PROD1 1
ORD2 PROD2 1
ORD2 PROD2 1
ORD3 PROD3 1
ORD3 PROD3 1
ORD3 PROD3 1

db<>fiddle