Несколько CTE в одном запросе

Можно ли объединить несколько CTE в одном запросе с помощью arel? Я ищу способ получить такой результат:

WITH 'cte1' AS (
...
),
WITH RECURSIVE 'cte2' AS (
...
),
WITH 'cte3' AS (
...
)
SELECT ... FROM 'cte3' WHERE ...

Как видите, у меня есть один рекурсивный CTE и два нерекурсивных.


person axvm    schedule 07.02.2016    source источник
comment
Имя CTE является идентификатором. Идентификаторы не должны заключаться в одинарные кавычки WITH 'cte1' недопустимо (например, from foobar as 'bla')   -  person a_horse_with_no_name    schedule 07.02.2016


Ответы (2)


Используйте ключевое слово WITH один раз вверху. Если какое-либо из ваших общих табличных выражений (CTE) является рекурсивным (rCTE), вы также должны добавить ключевое слово RECURSIVE сверху once, даже если не все CTE являются рекурсивными:

WITH RECURSIVE
  cte1 AS (...)         -- can still be non-recursive
, cte2 AS (SELECT ...
           UNION ALL
           SELECT ...)  -- recursive term
, cte3 AS (...)
SELECT ... FROM cte3 WHERE ...

Руководство:

Если указано RECURSIVE, оно разрешает подзапросу SELECT ссылаться на себя по имени.

Жирный акцент мой. И еще познавательнее:

Еще один эффект RECURSIVE заключается в том, что WITH запросы не нужно упорядочивать: запрос может ссылаться на другой запрос, который находится позже в списке. (Однако циклические ссылки или взаимная рекурсия не реализованы.) Без RECURSIVE запросы WITH могут ссылаться только на одноуровневые запросы WITH, находящиеся ранее в списке WITH.

Жирный акцент снова мой. Это означает, что порядок предложений WITH бессмыслен при использовании ключевого слова RECURSIVE.

Кстати, поскольку cte1 и cte2 в этом примере не упоминаются во внешнем SELECT и сами являются простыми командами SELECT (без побочных эффектов), они никогда не выполняются (если не указаны в cte3).

person Erwin Brandstetter    schedule 07.02.2016

да. Вы не повторяете WITH. Вы просто используете запятую:

WITH cte1 AS (
...
),
     cte2 AS (
...
),
     cte3 AS (
...
)
SELECT ... FROM 'cte3' WHERE ...

И: используйте только одинарные кавычки для строковых констант и констант даты. Не используйте их для псевдонимов столбцов. В любом случае они не разрешены для имен CTE.

person Gordon Linoff    schedule 07.02.2016
comment
Но если мне нужен один рекурсивный CTE с двумя нерекурсивными? - person axvm; 07.02.2016
comment
Но cte1, cte2, cte3 не могут ссылаться друг на друга, верно? - person thadk; 21.04.2020
comment
@тадк . . . Они могут, на это нет никаких ограничений, за исключением того, что CTE должны быть определены до их использования. - person Gordon Linoff; 21.04.2020
comment
Спасибо! Я не мог заставить его работать, когда пытался сослаться на cte1 внутри cte2, но, возможно, я сделал опечатку или что-то в этом роде. - person thadk; 09.05.2020