Как использовать выражение Common Table с параметрами?
У меня есть хранимая процедура с двумя CTE. Второй CTE имеет параметр
WITH path_sequences
AS
(
),
WITH categories
AS
(
... WHERE CategoryId = @CategoryId
// I dont know how to get this initial parameter inside the CTE
)
SELECT * FROM path_sequences p
JOIN categories c
ON p.CategoryId = c.CategoryId
Начальный параметр, который мне нужно получить во втором TCE, p.CategoryId. Как мне это сделать без необходимости создания другой хранимой процедуры для размещения второго CTE?
Спасибо за помощь
Ответы
Ответ 1
Вы можете создать функцию с табличной оценкой
create function ftCategories
(
@CategoryID int
)
returns table
as return
with categories as (
... WHERE CategoryId = @CategoryId
)
select Col1, Col2 ...
from categories
и использовать его как
SELECT *
FROM path_sequences p
cross apply ftCategories(p.CategoryId) c
Ответ 2
Я создал простой запрос, используя ваш код. Вы можете использовать его как -
DECLARE @CategoryId INT
SET @CategoryId = 1
;WITH path_sequences
AS
(
SELECT 1 CategoryId
),
categories
AS
(
SELECT 1 CategoryId WHERE 1 = @CategoryId
)
SELECT * FROM path_sequences p
JOIN categories c
ON p.CategoryId = c.CategoryId
Ответ 3
Сначала удалите второй WITH, разделите каждый cte только запятой. Затем вы можете добавить такие параметры:
DECLARE @category INT -- <~~ Parameter outside of CTEs
WITH
MyCTE1 (col1, col2) -- <~~ were poorly named param1 and param2 previously
AS
(
SELECT blah blah
FROM blah
WHERE CategoryId = @CategoryId
),
MyCTE2 (col1, col2) -- <~~ were poorly named param1 and param2 previously
AS
(
)
SELECT *
FROM MyCTE2
INNER JOIN MyCTE1 ON ...etc....
ИЗМЕНИТЬ (и ПОДТВЕРЖДЕНИЕ):
Я переименовал столбцы из param1 и param2 в col1 и col2 (это то, что я имел в виду изначально).
В моем примере предполагается, что каждый SELECT имеет ровно два столбца. Столбцы являются необязательными, если вы хотите вернуть все столбцы из базового запроса, и эти имена уникальны. Если у вас больше или меньше столбцов, чем у SELECT, вам нужно будет указать имена.
Вот еще один пример:
Таблица:
CREATE TABLE Employee
(
Id INT NOT NULL IDENTITY PRIMARY KEY CLUSTERED,
FirstName VARCHAR(50) NOT NULL,
LastName VARCHAR(50) NOT NULL,
ManagerId INT NULL
)
Заполнить таблицу несколькими строками:
INSERT INTO Employee
(FirstName, LastName, ManagerId)
VALUES
('Donald', 'Duck', 5)
INSERT INTO Employee
(FirstName, LastName, ManagerId)
VALUES
('Micky', 'Mouse', 5)
INSERT INTO Employee
(FirstName, LastName, ManagerId)
VALUES
('Daisy', 'Duck', 5)
INSERT INTO Employee
(FirstName, LastName, ManagerId)
VALUES
('Fred', 'Flintstone', 5)
INSERT INTO Employee
(FirstName, LastName, ManagerId)
VALUES
('Darth', 'Vader', null)
INSERT INTO Employee
(FirstName, LastName, ManagerId)
VALUES
('Bugs', 'Bunny', null)
INSERT INTO Employee
(FirstName, LastName, ManagerId)
VALUES
('Daffy', 'Duck', null)
, CTE:
DECLARE @ManagerId INT = 5;
WITH
MyCTE1 (col1, col2, col3, col4)
AS
(
SELECT *
FROM Employee e
WHERE 1=1
AND e.Id = @ManagerId
),
MyCTE2 (colx, coly, colz, cola)
AS
(
SELECT e.*
FROM Employee e
INNER JOIN MyCTE1 mgr ON mgr.col1 = e.ManagerId
WHERE 1=1
)
SELECT
empsWithMgrs.colx,
empsWithMgrs.coly,
empsWithMgrs.colz,
empsWithMgrs.cola
FROM MyCTE2 empsWithMgrs
Обратите внимание, что в CTE столбцы псевдонимы. MyCTE1 предоставляет столбцы как ссылки col1, col2, col3, col4 и MyCTE2 MyCTE1.col1, когда он ссылается на него. Обратите внимание, что окончательный выбор использует имена столбцов MyCTE2.
Результаты:
![введите описание изображения здесь]()
Ответ 4
Этот синтаксис предназначен для внешних псевдонимов:
-- CTES With External Aliases:
WITH Sales_CTE (SalesPersonID, SalesOrderID, SalesYear)
AS
-- Define the CTE query.
(
SELECT SalesPersonID, SalesOrderID, YEAR(OrderDate) AS SalesYear
FROM Sales.SalesOrderHeader
WHERE SalesPersonID IS NOT NULL
)
Единственный способ добавления параметров - использовать переменные области видимости так:
--Declare a variable:
DECLARE @category INT
WITH
MyCTE1 (exName1, exName2)
AS
(
SELECT <SELECT LIST>
FROM <TABLE LIST>
--Use the variable as 'a parameter'
WHERE CategoryId = @CategoryId
)
Ответ 5
Для тех, кто все еще борется с этим, единственное, что вам нужно, это прекратить объявление переменных точкой с запятой перед CTE. Больше ничего не требуется.
DECLARE @test AS INT = 42;
WITH x
AS (SELECT @test AS 'Column')
SELECT *
FROM x
Результаты:
Column
-----------
42
(1 row affected)