Giữ cho nó đơn giản và cách thực hiện nhiều CTE trong một truy vấn


156

Tôi có truy vấn T-SQL đơn giản này, nó phát ra một loạt các cột từ một bảng và cũng tham gia thông tin từ các bảng liên quan khác .

Mô hình dữ liệu của tôi rất đơn giản. Tôi có một sự kiện theo lịch trình, với những người tham gia. Tôi cần biết có bao nhiêu người tham gia trong mỗi sự kiện.

Giải pháp của tôi cho vấn đề này là thêm một CTE để nhóm các sự kiện theo lịch trình và đếm số lượng người tham gia.

Điều này sẽ cho phép tôi tham gia vào thông tin đó cho mỗi sự kiện theo lịch trình. Giữ truy vấn đơn giản.

Tôi muốn giữ cho các truy vấn của mình đơn giản, tuy nhiên, nếu tôi trong tương lai cần phải có kết quả tạm thời bổ sung có thể truy cập trong truy vấn đơn giản của mình, tôi phải làm gì?

Tôi thực sự thích nó, nếu tôi có thể có nhiều CTE nhưng tôi không thể, phải không? lựa chọn của tôi là gì đây?

Tôi đã loại trừ lượt xem và thực hiện mọi thứ ở lớp dữ liệu ứng dụng. Tôi thích cách ly các truy vấn SQL của tôi.

Câu trả lời:


297

Bạn có thể có nhiều CTEs trong một truy vấn, cũng như sử dụng lại CTE:

WITH    cte1 AS
        (
        SELECT  1 AS id
        ),
        cte2 AS
        (
        SELECT  2 AS id
        )
SELECT  *
FROM    cte1
UNION ALL
SELECT  *
FROM    cte2
UNION ALL
SELECT  *
FROM    cte1

Tuy nhiên, lưu ý rằng SQL Servercó thể đánh giá lại CTEmỗi lần nó được truy cập, vì vậy nếu bạn đang sử dụng các giá trị như RAND(), NEWID()v.v., chúng có thể thay đổi giữa các CTEcuộc gọi.


3
Nó thật đơn giản. tài liệu MSDN hơi mơ hồ về vấn đề này, tôi không thể tìm thấy kết luận nào. Cảm ơn rât nhiều!
John Leidegren

1
Nó được ghi lại trong VỚI common_table_expression (Transact-SQL) . Bạn có thể thấy điều này là trong phần cú pháp (lưu ý đặc biệt của [ ,...n ]trong [ WITH <common_table_expression> [ ,...n ] ]. Ví dụ C, "Sử dụng nhiều định nghĩa CTE trong một truy vấn duy nhất," gọi này ra một cách rõ ràng. Đáng buồn thay, ví dụ này không được cung cấp trong tài liệu cho SQL 2008 và cũ hơn (ví dụ, ví dụ không được cung cấp khi OP đăng câu hỏi).
Brian

Tôi nhận được gấp đôi số lượng hồ sơ về việc này: /
Tom Stickel

@TomStickel chỉ thử sử dụng một nửa truy vấn, trước lần truy vấn cuối cùngUNION ALL
Quassnoi

@Quassnoi Có mà làm việc. Tôi đã làm điều đó sau khi viết bình luận. Không chắc tại sao liên minh thứ 2 thậm chí còn ở đó ...
Tom Stickel

89

Bạn chắc chắn có thể có nhiều CTE trong một biểu thức truy vấn. Bạn chỉ cần tách chúng bằng dấu phẩy. Đây là một ví dụ. Trong ví dụ dưới đây, có hai CTE. Một cái được đặt tên CategoryAndNumberOfProductsvà cái thứ hai được đặt tên ProductsOverTenDollars.

WITH CategoryAndNumberOfProducts (CategoryID, CategoryName, NumberOfProducts) AS
(
   SELECT
      CategoryID,
      CategoryName,
      (SELECT COUNT(1) FROM Products p
       WHERE p.CategoryID = c.CategoryID) as NumberOfProducts
   FROM Categories c
),

ProductsOverTenDollars (ProductID, CategoryID, ProductName, UnitPrice) AS
(
   SELECT
      ProductID,
      CategoryID,
      ProductName,
      UnitPrice
   FROM Products p
   WHERE UnitPrice > 10.0
)

SELECT c.CategoryName, c.NumberOfProducts,
      p.ProductName, p.UnitPrice
FROM ProductsOverTenDollars p
   INNER JOIN CategoryAndNumberOfProducts c ON
      p.CategoryID = c.CategoryID
ORDER BY ProductName

5
@ John
Peter Majeed
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.