Können Sie verschachtelte WITH-Klauseln für allgemeine Tabellenausdrücke erstellen?

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

Funktioniert so etwas? Ich habe es früher versucht, aber ich konnte es nicht zum Laufen bringen.

Joe Phillips
quelle

Antworten:

301

Obwohl nicht streng verschachtelt, können Sie allgemeine Tabellenausdrücke verwenden, um frühere Abfragen in nachfolgenden wiederzuverwenden.

Dazu wäre die Form der Aussage, nach der Sie suchen

WITH x AS 
(
    SELECT * FROM MyTable
), 
y AS 
(
    SELECT * FROM x
)
SELECT * FROM y
Spender
quelle
2
Vielen Dank. Ich konnte es in Oracle tun: MIT J AS (SELECT 1 AS ONE FROM DUAL), Q AS (SELECT J. *, 2 AS TWO FROM J) SELECT * FROM Q
Jason TEPOORTEN
5
Dies ist nicht verschachtelt
Symbiont
13
Im Wesentlichen bedeutet der Beitrag, dass Sie es nicht tun können , aber es ist kein großes Problem.
Peter - Wiedereinsetzung Monica
2
Ja, dies ist eine akzeptable Antwort, denn was ich mit dem Verschachteln erreichen wollte, ist dasselbe, was mir das ohnehin gibt
Joe Phillips
2
Die Aussage, dass dies nicht verschachtelt ist, nur weil sich Abfrage 2 nicht in der Klammer von Abfrage 1 befindet, klingt nach einem schwachen Argument. Ich denke, es ist verschachtelt (nicht rekursiv verschachtelt), da Abfrage 2 das Ergebnis von Abfrage 1 verwendet, das auch beim Verschachteln auftritt. Ist definiert, dass die Verschachtelung nur erfolgen kann, wenn sich ein Kind in den übergeordneten Klammern (oder ähnlichen Symbolen) befindet?
Christiaan Westerbeek
11

Sie können Folgendes tun, was als rekursive Abfrage bezeichnet wird:

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

Möglicherweise benötigen Sie diese Funktionalität nicht. Ich habe Folgendes getan, um meine Abfragen besser zu organisieren:

WITH y 
AS
(
  SELECT * 
  FROM MyTable
  WHERE [base_condition]
),
x
AS
(
  SELECT * 
  FROM y
  WHERE [something_else]
)
SELECT * 
FROM x
David Andres
quelle
7

Mit funktioniert nicht eingebettet, aber es funktioniert nacheinander

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

BEARBEITEN Die Syntax wurde korrigiert ...

Schauen Sie sich auch das folgende Beispiel an

SQLFiddle DEMO

Adriaan Stander
quelle
0

Diese Antworten sind ziemlich gut, aber wenn Sie die Artikel richtig bestellen möchten, sollten Sie sich diesen Artikel http://dataeducation.com/dr-output-or-how-i-learned-to-stop ansehen -sorgen und-lieben-die-Verschmelzung

Hier ist ein Beispiel für seine Anfrage.

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
quelle
Meine ursprüngliche Frage sagte nie etwas über das Zusammenführen von Daten aus. Es hätte genauso gut Daten verbinden können
Joe Phillips
0

Ich habe versucht, die Zeit zwischen Ereignissen zu messen, mit Ausnahme eines Eintrags, der mehrere Prozesse zwischen Start und Ende aufweist. Ich brauchte dies im Zusammenhang mit anderen einzeiligen Prozessen.

Ich habe ein select mit einem inneren Join als meine select-Anweisung innerhalb des N-ten cte verwendet. Das zweite cte musste ich das Startdatum auf X und das Enddatum auf Y extrahieren und 1 als ID-Wert für den linken Join verwenden, um sie in eine einzelne Zeile zu setzen.

Funktioniert für mich, hoffe das hilft.

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

.... andere ctes

natur3
quelle
0

Verschachteltes 'Mit' wird nicht unterstützt, aber Sie können das zweite Mit immer als Unterabfrage verwenden, zum Beispiel:

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
quelle
-1

Wir können verschachtelte cte erstellen. Bitte sehen Sie das folgende cte im Beispiel

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

select * from cte_data,cte_data1
Subhransu Panda
quelle
4
Du bist ein bisschen zu spät zur Party;)
Joe Phillips
4
und das sind aufeinanderfolgende CTEs, keine verschachtelten CTEs
Meower68