Простота и как сделать несколько CTE в запросе - PullRequest
128 голосов
/ 26 января 2010

У меня есть этот простой запрос T-SQL, он генерирует несколько столбцов из таблицы, а также объединяет информацию из других связанных таблиц.

Моя модель данных проста. У меня запланированное мероприятие с участниками. Мне нужно знать, сколько участников участвует в каждом мероприятии.

Мое решение для этого состоит в том, чтобы добавить CTE, который группирует запланированные события и подсчитывает количество участников.

Это позволит мне присоединиться к этой информации для каждого запланированного события. Сохранение запроса простым.

Я хотел бы, чтобы мои запросы были простыми, однако, если мне когда-нибудь понадобятся дополнительные временные результаты, доступные во время моего простого запроса, что мне делать?

Мне бы очень хотелось, если бы у меня было несколько CTE, но я не могу, верно? Какие у меня есть варианты?

Я исключил представления и действия на уровне данных приложения. Я предпочитаю изолировать свои SQL-запросы.

Ответы [ 2 ]

242 голосов
/ 26 января 2010

Вы можете иметь несколько CTE s в одном запросе, а также повторно использовать 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

Обратите внимание, однако, что SQL Server может пересматривать CTE каждый раз, когда к нему обращаются, поэтому, если вы используете такие значения, как RAND(), NEWID() и т. Д., Они могут измениться между вызовами CTE.

74 голосов
/ 26 января 2010

Вы, безусловно, можете иметь несколько CTE в одном выражении запроса. Вам просто нужно отделить их запятой. Вот пример. В приведенном ниже примере есть два CTE. Один с именем CategoryAndNumberOfProducts, а второй с именем 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
...