Как работает рекурсивный запрос WITH в Oracle?Когда это входит в цикл? - PullRequest
0 голосов
/ 28 января 2019

У меня есть сценарий, в котором я должен отображать строку 'n' количество раз в зависимости от значения в столбце количества.

Item       Qty
abc        2 
cde        1

Item       Qty
abc        1
abc        1
cde        1

Я хочу преобразовать первую таблицу во вторую.

Я обнаружил, что должен использовать рекурсивный запрос WITH.

Мой якорьучастник возвращает исходную таблицу.

SELECT ITEM, QTY
           FROM lines
          WHERE     
                JOB = TO_NUMBER ('1')
                AND ITEM IN
                       (SELECT PART
                          FROM PICK
                         WHERE DELIVERY = '2')

Мой рекурсивный член выглядит следующим образом.

SELECT CTE.ITEM, (CTE.QTY - 1) QTY
           FROM CTE
                INNER JOIN
                (SELECT ITEM, QTY
                   FROM LINES
                  WHERE JOB_ID = TO_NUMBER ('1')
                        AND ITEM IN
                               (SELECT PART
                                  FROM PICK
                                 WHERE DELIVERY = '2'
                                       )) T
                   ON CTE.ITEM = T.ITEM
          WHERE CTE.QTY > 1

Моя цель состоит в том, чтобы сначала получить все части и количества, а затем все части с qty> 1 на рекурсивном шаге генерирует новые строки, которые будут добавлены к исходному набору результатов, и qty, отображаемое в новых строках, будет (исходное qty для этой части - 1).Рекурсия будет продолжаться, пока qty не станет 1 для всех частей.

Итак, это то, что у меня было в конце.

WITH CTE (ITEM, QTY)
AS (
SELECT ITEM, QTY
           FROM lines
          WHERE     
                JOB = TO_NUMBER ('1')
                AND ITEM IN
                       (SELECT PART
                          FROM PICK
                         WHERE DELIVERY = '2')
UNION ALL
SELECT CTE.ITEM, (CTE.QTY - 1) QTY
           FROM CTE
                INNER JOIN
                (SELECT ITEM, QTY
                   FROM LINES
                  WHERE JOB_ID = TO_NUMBER ('1')
                        AND ITEM IN
                               (SELECT PART
                                  FROM PICK
                                 WHERE DELIVERY = '2'
                                       )) T
                   ON CTE.ITEM = T.ITEM
          WHERE CTE.QTY > 1)
  SELECT ITEM, QTY
    FROM CTE
ORDER BY 1, 2 DESC

Я получаю следующую ошибку, когда пытаюсь указать выше: «ORA-32044: обнаружен цикл при выполнении рекурсивного запроса WITH»

Как это попасть в цикл?Что я упустил в его работе?

Кроме того, после прочтения с другого веб-сайта, если я использовал «предложение цикла».Мне удалось остановить цикл.

Я использовал следующее предложение:

       CYCLE  
       QUANTITY   
       SET                                    
       END TO '1'                               
       DEFAULT '0'

Если бы я использовал это до оператора select.Я получаю желаемый результат, но я не чувствую, что это правильный путь.Что именно делает пункт?Как правильно его использовать?

1 Ответ

0 голосов
/ 29 января 2019

Установка Oracle :

CREATE TABLE lines ( Item, Qty ) AS
SELECT 'abc', 2 FROM DUAL UNION ALL 
SELECT 'cde', 1 FROM DUAL;

CREATE TABLE pick ( part, delivery ) AS
SELECT 'abc', 2 FROM DUAL UNION ALL
SELECT 'cde', 2 FROM DUAL;

Запрос 1 : Использование иерархического запроса:

SELECT Item,
       COLUMN_VALUE AS qty
FROM   lines l
       CROSS JOIN
       TABLE(
         CAST(
           MULTISET(
             SELECT 1
             FROM   DUAL
             CONNECT BY LEVEL <= l.Qty
           )
           AS SYS.ODCINUMBERLIST
         )
       ) t
WHERE  item IN ( SELECT part FROM pick WHERE delivery = 2 )

Запрос 2 : Использование рекурсивного предложения факторинга подзапроса:

WITH rsqfc ( item, qty ) AS (
  SELECT item, qty
  FROM   lines l
  WHERE  item IN ( SELECT part FROM pick WHERE delivery = 2 )
UNION ALL
  SELECT item, qty - 1
  FROM   rsqfc
  WHERE  qty > 1
)
SELECT item, 1 AS qty
FROM   rsqfc;

Вывод :

ITEM | QTY
:--- | --:
abc  |   1
abc  |   1
cde  |   1

db <> fiddle здесь

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...