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

我正在使用CTE递归查询来获得低于输出的值,但不知道为什么会这样 使用查询";执行递归时检测到抛出";循环。有人能告诉我我的查询哪里错了吗?

我的问题:

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)
选择订单ID、产品ID、数量 来自CTE;

表/数据脚本:

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;

解决方案

在递归成员中,您当前只加入了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;

在最终选择中分配固定的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 数量
ORD1 打印1 1
ORD1 打印1 1
ORD1 打印1 1
ORD1 打印1 1
ORD1 打印1 1
ORD2 ProD2 1
ORD2 ProD2 1
ORD3 PROD3 1
ORD3 PROD3 1
ORD3 PROD3 1

db<>fiddle

相关文章