Pouvez-vous créer des clauses WITH imbriquées pour les expressions de table communes?

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

Est-ce que quelque chose comme ça fonctionne? Je l'ai essayé plus tôt mais je n'ai pas pu le faire fonctionner.

Joe Phillips
la source

Réponses:

302

Bien que n'étant pas strictement imbriquées, vous pouvez utiliser des expressions de table courantes pour réutiliser les requêtes précédentes dans les suivantes.

Pour ce faire, la forme de la déclaration que vous recherchez serait

WITH x AS 
(
    SELECT * FROM MyTable
), 
y AS 
(
    SELECT * FROM x
)
SELECT * FROM y
dépensier
la source
2
Merci beaucoup. J'ai pu le faire dans Oracle: WITH J AS (SELECT 1 AS ONE FROM DUAL), Q AS (SELECT J. *, 2 AS TWO FROM J) SELECT * FROM Q
Jason TEPOORTEN
5
ce n'est pas imbriqué
symbiont
14
Essentiellement, le message signifie que vous ne pouvez pas le faire , mais ce n'est pas un gros problème.
peterh
2
Oui, c'est une réponse acceptable car ce que j'essayais de réaliser avec l'imbrication est la même chose que cela finit par me donner de toute façon
Joe Phillips
2
Dire que cela n'est pas imbriqué, simplement parce que la requête 2 n'est pas entre les parenthèses de la requête 1, sonne comme un argument faible. Je pense qu'il est imbriqué (pas récursivement imbriqué), car la requête 2 utilise le résultat de la requête 1, qui se produit également avec l'imbrication. Est-il défini que l'imbrication ne peut avoir lieu que lorsqu'un enfant est entre ses parenthèses (ou symboles similaires)?
Christiaan Westerbeek
11

Vous pouvez effectuer les opérations suivantes, appelées requêtes récursives:

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

Vous n'avez peut-être pas besoin de cette fonctionnalité. J'ai fait ce qui suit pour mieux organiser mes requêtes:

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

Avec ne fonctionne pas intégré, mais cela fonctionne consécutivement

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

EDIT Correction de la syntaxe ...

Jetez également un œil à l'exemple suivant

DÉMO SQLFiddle

Adriaan Stander
la source
0

Ces réponses sont plutôt bonnes, mais en ce qui concerne la bonne commande des articles, vous feriez mieux de consulter cet article http://dataeducation.com/dr-output-or-how-i-learned-to-stop -inquiéter-et-aimer-la-fusion

Voici un exemple de sa requête.

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
la source
Ma question initiale n'a jamais rien dit sur l'union des données. Cela aurait pu tout aussi facilement rejoindre des données
Joe Phillips
0

J'essayais de mesurer le temps entre les événements à l'exception de ce qu'une entrée qui a plusieurs processus entre le début et la fin. J'en avais besoin dans le contexte d'autres processus monolignes.

J'ai utilisé un select avec une jointure interne comme instruction de sélection dans le Nth cte. Le deuxième cte dont j'avais besoin pour extraire la date de début sur X et la date de fin sur Y et utilisé 1 comme valeur d'identifiant pour la jointure gauche pour les mettre sur une seule ligne.

Fonctionne pour moi, j'espère que cela aide.

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

.... autres ctes

natur3
la source
0

Nested 'With' n'est pas pris en charge, mais vous pouvez toujours utiliser le second With comme sous-requête, par exemple:

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
la source
-1

nous pouvons créer un cte imbriqué.Veuillez voir le cte ci-dessous dans l'exemple

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

select * from cte_data,cte_data1
Subhransu Panda
la source
4
Vous êtes un peu en retard à la fête;)
Joe Phillips
4
et ce sont des CTE consécutifs, pas des CTE imbriqués
Meower68