คุณสามารถสร้างคำสั่งซ้อนด้วย Common สำหรับนิพจน์ตารางทั่วไปได้หรือไม่


คำตอบ:


302

แม้ว่าจะไม่ซ้อนกันอย่างเข้มงวดคุณสามารถใช้นิพจน์ตารางทั่วไปเพื่อนำคิวรีก่อนหน้านี้มาใช้ซ้ำในนิพจน์ที่ตามมา

หากต้องการทำสิ่งนี้รูปแบบของคำสั่งที่คุณต้องการจะเป็น

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

2
ขอบคุณมาก. ฉันสามารถทำได้ใน Oracle: กับ J AS (เลือก 1 อย่างจาก DUAL), Q AS (เลือก J *, 2
เท่ากับ

5
นี่ไม่ซ้อนกัน
symbiont

14
การโพสต์หมายความว่าคุณไม่สามารถทำได้แต่มันไม่ใช่ปัญหาใหญ่
peterh - Reinstate Monica

2
ใช่นี่เป็นคำตอบที่ยอมรับได้เพราะสิ่งที่ฉันพยายามทำโดยใช้การซ้อนคือสิ่งเดียวกันที่ทำให้ฉันอยู่ดี
Joe Phillips

2
ระบุว่าสิ่งนี้ไม่ซ้อนกันเพียงเพราะแบบสอบถาม 2 ไม่อยู่ในวงเล็บของแบบสอบถาม 1 ดูเหมือนจะเป็นอาร์กิวเมนต์ที่อ่อนแอ ฉันคิดว่ามันซ้อนกัน (ไม่ซ้อนกันซ้ำ) เนื่องจากแบบสอบถาม 2 ใช้ผลลัพธ์ของแบบสอบถาม 1 ซึ่งเกิดขึ้นกับการซ้อนกัน มีการกำหนดไว้ว่าการซ้อนกันทำได้เฉพาะเมื่อเด็กอยู่ในเครื่องหมายวงเล็บหลัก (หรือสัญลักษณ์ที่คล้ายกัน) เท่านั้น
Christiaan Westerbeek

11

คุณสามารถทำสิ่งต่อไปนี้ซึ่งเรียกว่าแบบสอบถามแบบเรียกซ้ำ:

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

คุณอาจไม่ต้องการฟังก์ชั่นนี้ ฉันได้ทำสิ่งต่อไปนี้เพื่อจัดระเบียบแบบสอบถามของฉันให้ดีขึ้นแล้ว:

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

7

ด้วยไม่ทำงานฝังตัว แต่จะทำงานต่อเนื่องกัน

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

แก้ไข แก้ไขไวยากรณ์ ...

ดูที่ตัวอย่างต่อไปนี้ด้วย

ตัวอย่าง SQLFiddle


0

คำตอบเหล่านี้ค่อนข้างดี แต่ถ้าคุณได้รับคำสั่งซื้ออย่างถูกต้องคุณควรดูบทความนี้ http://dataeducation.com/dr-output-or-how-i-learned-to-stop -worrying และความรักที่ผสาน

นี่คือตัวอย่างของการค้นหาของเขา

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

คำถามเดิมของฉันไม่เคยพูดอะไรเกี่ยวกับการรวมข้อมูลเข้าด้วยกัน อาจเป็นเพียงการเข้าร่วมข้อมูลได้อย่างง่ายดาย
Joe Phillips

0

ฉันพยายามวัดเวลาระหว่างเหตุการณ์โดยมีข้อยกเว้นว่ามีรายการใดบ้างที่มีหลายกระบวนการระหว่างการเริ่มต้นและสิ้นสุด ฉันต้องการสิ่งนี้ในบริบทของกระบวนการสายเดี่ยวอื่น ๆ

ฉันใช้การเลือกด้วยการเข้าร่วมภายในเป็นคำสั่งการเลือกของฉันภายใน Nth cte cte ตัวที่สองที่ฉันต้องการเพื่อดึงวันที่เริ่มต้นบน X และวันที่สิ้นสุดบน Y และใช้ 1 เป็นค่า id เพื่อออกจากการเข้าร่วมเพื่อวางไว้ในบรรทัดเดียว

ใช้งานได้สำหรับฉันหวังว่าจะช่วยได้

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

.... อื่น ๆ


0

ไม่รองรับ 'พร้อม' แต่คุณสามารถใช้คำสั่งย่อยที่สองเป็นแบบสอบถามย่อยได้เสมอ:

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

เราสามารถสร้าง cte.please ซ้อนกันดู cte ด้านล่างในตัวอย่าง

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

select * from cte_data,cte_data1

4
คุณไปงานเลี้ยงสายนิดหน่อย;)
Joe Phillips

4
และนั่นคือ CTE ติดต่อกันไม่ใช่ CTE ที่ซ้อนกัน
Meower68
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.