Зробити це просто та як зробити кілька CTE у запиті


156

У мене цей простий T-SQL-запит, він випускає купу стовпців із таблиці, а також приєднує інформацію з інших пов’язаних таблиць.

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

Моє рішення для цього - додати CTE, який групує заплановані заходи та підраховує кількість учасників.

Це дозволить мені долучитися до цієї інформації за запланованою подією. Простий запит.

Мені подобається, щоб мої запити були простими, проте якщо мені в майбутньому потрібно мати додаткові тимчасові результати, доступні під час мого простого запиту, що робити?

Мені б дуже хотілося, якби у мене було кілька CTE, але я не можу, правда? Які тут мої варіанти?

Я виключав погляди та виконуючи дії на рівні даних програми. Я віддаю перевагу ізольованим запитам SQL.

Відповіді:


297

Ви можете мати кілька CTEs в одному запиті, а також використовувати a 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викликами.


3
Це було так просто. документація MSDN була трохи нечіткою навколо проблеми, я не зміг знайти нічого переконливого. Велике спасибі!
Джон Лейдегрен

1
Це документально зафіксовано в Common_table_expression (Transact-SQL) . Це можна побачити в розділі синтаксису (зверніть особливу увагу на[ ,...n ] ін [ WITH <common_table_expression> [ ,...n ] ]. Приклад C, «Використання декількох визначень КТРА в одному запиті,» називає це явно. До жаль, цей приклад не наводяться в документації по SQL 2008 і старше (тобто приклад не наводився, коли ОП розмістила питання).
Брайан

Я отримую подвійну кількість записів про це: /
Tom

@TomStickel спробуйте використовувати лише половину запиту до останнього UNION ALL
Quassnoi

@Quassnoi Так, це спрацювало. Я це зробив після написання коментаря. Не впевнений, чому цей 2-й союз навіть існує ...
Том

90

Ви, звичайно, можете мати кілька 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

5
@JohnLeidegren: розміщення правильної відповіді протягом 2 хвилин після першої правильної відповіді заслуговує на принаймні заяву, яку я дав, принаймні.
Пітер Маджед
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.