Можете ли вы создать вложенные предложения WITH для выражений общих таблиц?

184
WITH y AS (
    WITH x AS (
        SELECT * FROM MyTable
    )
    SELECT * FROM x
)
SELECT * FROM y

Что-то подобное работает? Я попробовал это раньше, но я не мог заставить его работать.

Джо Филлипс
источник

Ответы:

302

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

Для этого форма заявления, которое вы ищете, будет

WITH x AS 
(
    SELECT * FROM MyTable
), 
y AS 
(
    SELECT * FROM x
)
SELECT * FROM y
расточитель
источник
2
Большое спасибо. Я смог сделать это в Oracle: С J AS (ВЫБРАТЬ 1 КАК ОДИН ИЗ ДВОЙНОГО), Q AS (ВЫБРАТЬ J. *, 2 КАК ДВЕ ОТ J) ВЫБРАТЬ * ИЗ Q
Джейсон TEPOORTEN
5
это не гнездо
symbiont
14
По сути, почта означает, что вы не можете сделать это , но это не большая проблема.
Петер - Восстановить Монику
2
Да, это приемлемый ответ, потому что то, что я пытался достичь с помощью вложения - это то же самое, что в конечном итоге дает мне
Джо Филлипс
2
Утверждение, что это не является вложенным, только потому, что запрос 2 не находится в скобках запроса 1, звучит как слабый аргумент. Я думаю, что это вложенный (не рекурсивно вложенный), потому что запрос 2 использует результат запроса 1, который также происходит с вложением. Определено, что вложение может быть только тогда, когда дочерний элемент находится в пределах родительских (или похожих) символов в скобках?
Кристиан Вестербик
11

Вы можете сделать следующее, что называется рекурсивным запросом:

WITH y
AS
(
  SELECT x, y, z
  FROM MyTable
  WHERE [base_condition]

  UNION ALL

  SELECT x, y, z
  FROM MyTable M
  INNER JOIN y ON M.[some_other_condition] = y.[some_other_condition]
)
SELECT *
FROM y

Вам может не понадобиться эта функциональность. Я сделал следующее, чтобы лучше организовать свои запросы:

WITH y 
AS
(
  SELECT * 
  FROM MyTable
  WHERE [base_condition]
),
x
AS
(
  SELECT * 
  FROM y
  WHERE [something_else]
)
SELECT * 
FROM x
Дэвид Андрес
источник
7

С не работает встроенный, но работает последовательно

;WITH A AS(
...
),
B AS(
...
)
SELECT *
FROM A
UNION ALL
SELECT *
FROM B

РЕДАКТИРОВАТЬ Исправлен синтаксис ...

Также посмотрите на следующий пример

SQLFiddle DEMO

Адриан Стандер
источник
0

Эти ответы довольно хороши, но если вам нужно правильно оформить заказ, вам лучше посмотреть эту статью http://dataeducation.com/dr-output-or-how-i-learned-to-stop -worrying-и-любовь-The-слияние

Вот пример его запроса.

WITH paths AS ( 
    SELECT 
        EmployeeID, 
        CONVERT(VARCHAR(900), CONCAT('.', EmployeeID, '.')) AS FullPath 
    FROM EmployeeHierarchyWide 
    WHERE ManagerID IS NULL

    UNION ALL

    SELECT 
        ehw.EmployeeID, 
        CONVERT(VARCHAR(900), CONCAT(p.FullPath, ehw.EmployeeID, '.')) AS FullPath 
    FROM paths AS p 
        JOIN EmployeeHierarchyWide AS ehw ON ehw.ManagerID = p.EmployeeID 
) 
SELECT * FROM paths order by FullPath
Дон Роллинг
источник
Мой оригинальный вопрос никогда не говорил об объединении данных. Это могло быть так же легко, как объединение данных
Джо Филлипс
0

Я пытался измерить время между событиями, за исключением того, что одна запись имеет несколько процессов между началом и концом. Мне это нужно в контексте других однострочных процессов.

Я использовал выбор с внутренним объединением в качестве оператора выбора в N-м городе. Во втором cte мне нужно было извлечь начальную дату по X и конечную дату по Y и использовать 1 в качестве значения идентификатора для левого соединения, чтобы поместить их в одну строку.

У меня работает, надеюсь, это поможет.

cte_extract
as 
(
    select ps.Process as ProcessEvent
        , ps.ProcessStartDate 
        , ps.ProcessEndDate 
        -- select strt.*
    from dbo.tbl_some_table ps 
    inner join (select max(ProcessStatusId) ProcessStatusId 
                    from dbo.tbl_some_table 
                where Process = 'some_extract_tbl' 
                and convert(varchar(10), ProcessStartDate, 112) < '29991231'
                ) strt on strt.ProcessStatusId = ps.ProcessStatusID
), 
cte_rls
as 
(
    select 'Sample' as ProcessEvent, 
     x.ProcessStartDate, y.ProcessEndDate  from (
    select 1 as Id, ps.Process as ProcessEvent
        , ps.ProcessStartDate 
        , ps.ProcessEndDate
        -- select strt.*
    from dbo.tbl_some_table ps 
    inner join (select max(ProcessStatusId) ProcessStatusId 
                    from dbo.tbl_some_table 
                where Process = 'XX Prcss' 
                and convert(varchar(10), ProcessStartDate, 112) < '29991231'
                ) strt on strt.ProcessStatusId = ps.ProcessStatusID
    ) x
    left join (
        select 1 as Id, ps.Process as ProcessEvent
            , ps.ProcessStartDate 
            , ps.ProcessEndDate
            -- select strt.*
        from dbo.tbl_some_table ps 
        inner join (select max(ProcessStatusId) ProcessStatusId
                    from dbo.tbl_some_table 
                    where Process = 'YY Prcss Cmpltd' 
                    and convert(varchar(10), ProcessEndDate, 112) < '29991231'
                    ) enddt on enddt.ProcessStatusId = ps.ProcessStatusID
            ) y on y.Id = x.Id 
),

.... другие ctes

natur3
источник
0

Вложенное «С» не поддерживается, но вы всегда можете использовать второй «С» в качестве подзапроса, например:

WITH A AS (
                --WITH B AS ( SELECT COUNT(1) AS _CT FROM C ) SELECT CASE _CT WHEN 1 THEN 1 ELSE 0 END FROM B --doesn't work
                SELECT CASE WHEN count = 1 THEN 1 ELSE 0 END AS CT FROM (SELECT COUNT(1) AS count FROM dual)
                union all
                select 100 AS CT from dual
           )
              select CT FROM A
KOBER
источник
-1

мы можем создать вложенный cte.please смотрите ниже cte в примере

;with cte_data as 
(
Select * from [HumanResources].[Department]
),cte_data1 as
(
Select * from [HumanResources].[Department]
)

select * from cte_data,cte_data1
Субхрансу Панда
источник
4
Вы немного опоздали на вечеринку;)
Джо Филлипс
4
и это последовательные CTE, а не вложенные CTE
Meower68