È possibile creare clausole WITH nidificate per le espressioni di tabella comuni?
-
06-07-2019 - |
Domanda
WITH y AS (
WITH x AS (
SELECT * FROM MyTable
)
SELECT * FROM x
)
SELECT * FROM y
Funziona qualcosa del genere? L'ho provato prima ma non riuscivo a farlo funzionare.
Soluzione
Sebbene non sia strettamente nidificato, è possibile utilizzare espressioni di tabella comuni per riutilizzare le query precedenti in quelle successive.
Per fare ciò, la forma della dichiarazione che stai cercando sarebbe
WITH x AS
(
SELECT * FROM MyTable
),
y AS
(
SELECT * FROM x
)
SELECT * FROM y
Altri suggerimenti
Puoi fare quanto segue, che viene chiamato query ricorsiva:
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
With non funziona incorporato, ma funziona consecutivamente
;WITH A AS(
...
),
B AS(
...
)
SELECT *
FROM A
UNION ALL
SELECT *
FROM B
Modifica Risolto il problema con la sintassi ...
Inoltre, dai un'occhiata al seguente esempio
SQLFiddle DEMO
Queste risposte sono abbastanza 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 query.
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
possiamo creare cte.nidificati, vedere l'esempio cte di seguito
;with cte_data as
(
Select * from [HumanResources].[Department]
),cte_data1 as
(
Select * from [HumanResources].[Department]
)
select * from cte_data,cte_data1
Stavo cercando di misurare il tempo tra gli eventi, ad eccezione di una 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'Nth 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