Bạn có thể tạo các mệnh đề lồng nhau với các biểu thức bảng chung không?


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

Có một cái gì đó như thế này làm việc? Tôi đã thử nó sớm hơn nhưng tôi không thể làm cho nó hoạt động.

Câu trả lời:


301

Mặc dù không được lồng hoàn toàn, bạn có thể sử dụng các biểu thức bảng chung để sử dụng lại các truy vấn trước đó trong các truy vấn tiếp theo.

Để làm điều này, hình thức của tuyên bố bạn đang tìm kiếm sẽ là

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

2
Cảm ơn rât nhiều. Tôi đã có thể làm điều đó trong Oracle: VỚI J AS (CHỌN 1 NHƯ MỘT TỪ DUAL), Q AS (CHỌN J. *, 2 NHƯ HAI TỪ J) CHỌN * TỪ Q
Jason TEPOORTEN

5
đây không phải là lồng nhau
cộng sinh

13
Về cơ bản bài viết có nghĩa là, bạn không thể làm điều đó , nhưng nó không phải là một vấn đề lớn.
peterh - Phục hồi Monica

2
Vâng, đây là một câu trả lời chấp nhận được bởi vì những gì tôi đã cố gắng đạt được khi làm tổ là điều tương tự cuối cùng mang lại cho tôi
Joe Phillips

2
Nói rằng điều này không được lồng nhau, chỉ vì truy vấn 2 không nằm trong dấu ngoặc đơn của truy vấn 1, nghe có vẻ như là một đối số yếu. Tôi nghĩ rằng nó được lồng (không được lồng đệ quy), bởi vì truy vấn 2 sử dụng kết quả của truy vấn 1, cũng xảy ra với lồng nhau. Được định nghĩa rằng lồng chỉ có thể là khi một đứa trẻ nằm trong các ký hiệu cha mẹ (hoặc tương tự) của nó?
Christiaan Westerbeek

11

Bạn có thể thực hiện các thao tác sau, được gọi là truy vấn đệ quy:

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

Bạn có thể không cần chức năng này. Tôi đã làm như sau chỉ để tổ chức các truy vấn của tôi tốt hơn:

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

7

Với không hoạt động nhúng, nhưng nó hoạt động liên tiếp

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

EDIT Đã sửa lỗi cú pháp ...

Ngoài ra, hãy xem ví dụ sau

DEMO SQLFiddle


0

Những câu trả lời này khá tốt, nhưng khi có được các mặt hàng để đặt hàng đúng cách, bạn nên xem bài viết này http://dataeducation.com/dr-output-or-how-i-learned-to-stop lo lắng-và-yêu-hợp nhất

Đây là một ví dụ về truy vấn của anh ấy.

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

Câu hỏi ban đầu của tôi không bao giờ nói bất cứ điều gì về việc kết hợp dữ liệu với nhau. Nó có thể dễ dàng tham gia dữ liệu
Joe Phillips

0

Tôi đã cố gắng đo thời gian giữa các sự kiện ngoại trừ mục nào có nhiều quá trình giữa bắt đầu và kết thúc. Tôi cần điều này trong bối cảnh của các quy trình đơn dòng khác.

Tôi đã sử dụng một lựa chọn với một tham gia bên trong như là tuyên bố lựa chọn của tôi trong cte Nth. Cte thứ hai tôi cần để trích xuất ngày bắt đầu trên X và ngày kết thúc trên Y và sử dụng 1 làm giá trị id cho phép nối trái để đặt chúng trên một dòng duy nhất.

Làm việc cho tôi, hy vọng điều này sẽ giúp.

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

.... các byte khác


0

Nested 'With' không được hỗ trợ, nhưng bạn luôn có thể sử dụng With thứ hai như một truy vấn con, ví dụ:

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

chúng ta có thể tạo cte lồng nhau. Xin vui lòng xem cte dưới đây trong ví dụ

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

select * from cte_data,cte_data1

4
Bạn đến bữa tiệc muộn một chút;)
Joe Phillips

4
và đó là các CTE liên tiếp, không phải là các
CTE
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.