È possibile creare clausole WITH nidificate per le espressioni di tabella comuni?


Risposte:


302

Sebbene non sia strettamente nidificato, è possibile utilizzare espressioni di tabella comuni per riutilizzare le query precedenti in quelle successive.

Per fare questo, la forma dell'affermazione che stai cercando sarebbe

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

2
Grazie mille. Sono stato in grado di farlo in Oracle: CON J AS (SELEZIONA 1 COME UNO DA DOPPIO), Q COME (SELEZIONA J. *, 2 COME DUE DA J) SELEZIONA * DA Q
Jason TEPOORTEN

5
questo non è nidificato
simbionte il

14
In sostanza il post significa che non puoi farlo , ma non è un grosso problema.
Peter - Ripristina Monica

2
Sì, questa è una risposta accettabile perché quello che stavo cercando di ottenere con l'annidamento è la stessa cosa che mi dà comunque
Joe Phillips,

2
Affermare che questo non è nidificato, solo perché la query 2 non si trova tra parentesi della query 1, sembra un argomento debole. Penso che sia nidificato (non nidificato in modo ricorsivo), poiché la query 2 utilizza il risultato della query 1, che si verifica anche con l'annidamento. Si definisce che la nidificazione può avvenire solo quando un bambino si trova all'interno dei suoi simboli parentesi (o simili)?
Christiaan Westerbeek,

11

È possibile effettuare le seguenti operazioni, denominate query ricorsive:

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

Potrebbe non essere necessaria questa funzionalità. Ho fatto quanto segue solo per organizzare meglio le mie domande:

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

7

Con non funziona incorporato, ma funziona consecutivamente

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

EDIT Risolto il problema con la sintassi ...

Inoltre, dai un'occhiata al seguente esempio

SQLFiddle DEMO


0

Queste risposte sono piuttosto buone, ma per quanto riguarda la corretta ordinazione degli articoli, faresti meglio a guardare questo articolo http://dataeducation.com/dr-output-or-how-i-learned-to-stop -worrying-and-love-the-merge

Ecco un esempio della sua domanda.

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

La mia domanda originale non ha mai detto nulla sull'unione dei dati. Avrebbe potuto facilmente unire i dati
Joe Phillips,

0

Stavo cercando di misurare il tempo tra gli eventi, ad eccezione di quella voce che ha più processi tra l'inizio e la fine. Ne avevo bisogno nel contesto di altri processi a linea singola.

Ho usato un select con un join interno come mia dichiarazione select all'interno dell'ennesimo cte. Il secondo cte avevo bisogno di estrarre la data di inizio su X e la data di fine su Y e ho usato 1 come valore ID per unire a sinistra per metterli su una sola riga.

Funziona per me, spero che questo aiuti.

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

.... altri ctes


0

'Con' annidato non è supportato, ma è sempre possibile utilizzare il secondo con come sottoquery, ad esempio:

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

-1

possiamo creare cte nidificati. Si prega di vedere l'esempio cte sotto

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

select * from cte_data,cte_data1

4
Sei un po 'in ritardo alla festa;)
Joe Phillips il

4
e questo è CTE consecutivi, non CTE nidificati
Meower68
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.