Oracle
 sql >> Base de données >  >> RDS >> Oracle

Cycle détecté lors de l'exécution d'une requête récursive

Dans le membre récursif que vous ne rejoignez actuellement que sur a.product_id = b.product_id , plutôt que a.order_id = b.order_id AND a.product_id = b.product_id; ce qui n'a pas d'importance directe ici, mais le serait si différentes commandes incluaient les mêmes produits, ce qui est probablement le cas dans le monde réel.

Vos données et votre requête ne semblent pas avoir de cycle. Vous semblez trébucher sur ce qui semble être un bogue avec les jointures ANSI ; ajouter un cycle la clause ne révèle aucune ligne de cycle, comme prévu - et la fait fonctionner ! ; et cela fonctionne avec les jointures à l'ancienne :

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<>violon

Vous n'avez pas besoin de vous inscrire du tout cependant; vous pouvez faire :

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;

qui attribue la quantité fixe 1 dans la sélection finale, ou :

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;

qui l'attribue à l'intérieur et doit suivre la quantité d'origine en tant que nouvel alias.

Pour les deux, j'ai supprimé le + 1 de la comparaison des quantités, car cela l'arrêtait trop tôt ; avec un order by ajoutés, ils obtiennent tous les deux :

ORDER_ID PRODUCT_ID QUANTITÉ
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<>violon