Bisakah Anda membuat klausa bersarang DENGAN untuk Ekspresi Tabel Umum?

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

Apakah sesuatu seperti ini berfungsi? Saya sudah mencobanya sebelumnya, tetapi tidak berhasil.

Joe Phillips
sumber

Jawaban:

302

Meskipun tidak benar-benar bersarang, Anda bisa menggunakan ekspresi tabel umum untuk menggunakan kembali pertanyaan sebelumnya di yang berikutnya.

Untuk melakukan ini, bentuk pernyataan yang Anda cari adalah

WITH x AS 
(
    SELECT * FROM MyTable
), 
y AS 
(
    SELECT * FROM x
)
SELECT * FROM y
pemboros
sumber
2
Terima kasih banyak. Saya dapat melakukannya di Oracle: DENGAN J AS (PILIH 1 AS SATU DARI DUAL), Q AS (PILIH J. *, 2 AS DUA DARI J) PILIH * DARI Q
Jason TEPOORTEN
5
ini bukan bersarang
symbiont
14
Pada dasarnya postingan berarti, bahwa Anda tidak dapat melakukannya , tetapi itu bukan masalah besar.
peterh
2
Ya, ini adalah jawaban yang dapat diterima karena apa yang saya coba capai dengan bersarang adalah hal yang sama yang akhirnya memberi saya
Joe Phillips
2
Menyatakan bahwa ini bukan bersarang, hanya karena kueri 2 tidak di dalam kurung kueri 1, terdengar seperti argumen yang lemah. Saya pikir itu bersarang (tidak bersarang secara rekursif), karena kueri 2 menggunakan hasil kueri 1, yang terjadi dengan bersarang juga. Apakah didefinisikan bahwa bersarang hanya dapat terjadi ketika seorang anak berada dalam simbol kurung induknya (atau yang serupa)?
Christiaan Westerbeek
11

Anda dapat melakukan hal berikut, yang disebut sebagai kueri rekursif:

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

Anda mungkin tidak memerlukan fungsi ini. Saya telah melakukan yang berikut hanya untuk mengatur pertanyaan saya dengan lebih baik:

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

Dengan tidak bekerja tertanam, tetapi berhasil bekerja secara berurutan

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

EDIT Memperbaiki sintaks ...

Juga, lihat contoh berikut

SQLFiddle DEMO

Adriaan Stander
sumber
0

Jawaban-jawaban ini cukup bagus, tetapi sejauh mendapatkan item untuk dipesan dengan benar, Anda akan lebih baik melihat artikel ini http://dataeducation.com/dr-output-or-how-i-learned-to-stop -mencari-dan-cinta-penggabungan

Berikut ini contoh permintaannya.

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
sumber
Pertanyaan awal saya tidak pernah mengatakan apa pun tentang penyatuan data bersama. Bisa saja dengan mudah menggabungkan data
Joe Phillips
0

Saya mencoba mengukur waktu antara peristiwa dengan pengecualian entri apa yang memiliki banyak proses antara awal dan akhir. Saya membutuhkan ini dalam konteks proses jalur tunggal lainnya.

Saya menggunakan pilih dengan gabungan batin sebagai pernyataan pilih saya dalam Nte cte. Cte kedua saya perlu mengekstrak tanggal mulai pada X dan tanggal akhir pada Y dan menggunakan 1 sebagai nilai id untuk bergabung kiri untuk menempatkan mereka pada satu baris.

Bekerja untuk saya, semoga ini membantu.

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

.... ctes lainnya

natur3
sumber
0

Nested 'With' tidak didukung, tetapi Anda selalu dapat menggunakan With kedua sebagai subquery, misalnya:

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

kita dapat membuat nested cte.silakan lihat contoh cte di bawah ini

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

select * from cte_data,cte_data1
Subhransu Panda
sumber
4
Anda agak terlambat ke pesta;)
Joe Phillips
4
dan itu adalah CTE berturut-turut, bukan
CTE