Czy można utworzyć zagnieżdżone klauzule WITH dla typowych wyrażeń tabelowych?

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

Czy coś takiego działa? Próbowałem wcześniej, ale nie mogłem go uruchomić.

Joe Phillips
źródło

Odpowiedzi:

302

Chociaż nie są ściśle zagnieżdżone, możesz użyć typowych wyrażeń tabelowych, aby ponownie wykorzystać poprzednie zapytania w kolejnych.

Aby to zrobić, forma formularza, którego szukasz, byłaby

WITH x AS 
(
    SELECT * FROM MyTable
), 
y AS 
(
    SELECT * FROM x
)
SELECT * FROM y
wydać
źródło
2
Dziękuję Ci bardzo. Byłem w stanie to zrobić w Oracle: Z J AS (WYBIERZ 1 JAKO JEDEN Z PODWÓJNEGO), Q AS (WYBIERZ J. *, 2 JAK DWA Z J) WYBIERZ * Z Q
Jason TEPOORTEN
5
to nie jest zagnieżdżone
symbiont
14
Zasadniczo post oznacza, że nie możesz tego zrobić , ale nie jest to duży problem.
Peter - Przywróć Monikę
2
Tak, jest to akceptowalna odpowiedź, ponieważ to, co próbowałem osiągnąć dzięki zagnieżdżaniu, jest tym samym, co i tak daje mi ostatecznie
Joe Phillips
2
Stwierdzenie, że nie jest ono zagnieżdżone, tylko dlatego, że zapytanie 2 nie znajduje się w nawiasie zapytania 1, brzmi jak słaby argument. Myślę, że jest zagnieżdżony (nie zagnieżdżony rekurencyjnie), ponieważ zapytanie 2 wykorzystuje wynik zapytania 1, które występuje również podczas zagnieżdżania. Czy zdefiniowano, że zagnieżdżanie może nastąpić tylko wtedy, gdy dziecko znajduje się w nawiasach (lub podobnych) symbolach?
Christiaan Westerbeek,
11

Możesz wykonać następujące czynności, które są określane jako zapytanie rekurencyjne:

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

Ta funkcja może nie być potrzebna. Wykonałem następujące czynności, aby lepiej uporządkować moje zapytania:

WITH y 
AS
(
  SELECT * 
  FROM MyTable
  WHERE [base_condition]
),
x
AS
(
  SELECT * 
  FROM y
  WHERE [something_else]
)
SELECT * 
FROM x
David Andres
źródło
7

Z nie działa osadzony, ale działa kolejno

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

EDYTOWAĆ Naprawiono składnię ...

Zobacz także następujący przykład

SQLFiddle DEMO

Adriaan Stander
źródło
0

Odpowiedzi te są całkiem dobre, ale jeśli chodzi o prawidłowe zamawianie przedmiotów, lepiej zapoznaj się z tym artykułem http://dataeducation.com/dr-output-or-how-i-learned-to-stop -niepokojące-i-kochaj-scalenie

Oto przykład jego zapytania.

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
Don Rolling
źródło
Moje pierwotne pytanie nigdy nie mówiło nic o łączeniu danych razem. Równie łatwo mogło połączyć dane
Joe Phillips
0

Próbowałem zmierzyć czas między zdarzeniami, z wyjątkiem jednego wpisu, który ma wiele procesów między początkiem a końcem. Potrzebowałem tego w kontekście innych procesów jednoliniowych.

Użyłem select z wewnętrznym złączeniem jako mojej instrukcji select w Nte cte. Drugie cte potrzebowałem wyodrębnić datę początkową na X i datę końcową na Y i użyłem 1 jako wartości identyfikacyjnej, aby opuścić złączenie, aby umieścić je w jednym wierszu.

Działa dla mnie, mam nadzieję, że to pomaga.

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 
),

.... inne ctes

natur3
źródło
0

Zagnieżdżone „With” nie jest obsługiwane, ale zawsze możesz użyć drugiego With jako podzapytania, na przykład:

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
źródło
-1

możemy utworzyć zagnieżdżony plik cte. proszę zobaczyć poniższy przykład

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

select * from cte_data,cte_data1
Subhransu Panda
źródło
4
Spóźniłeś się trochę na imprezę;)
Joe Phillips,
4
i to są kolejne CTE, a nie zagnieżdżone CTE
Meower68