23

我有一个带有 2 个 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 的情况下做到这一点?

感谢您的帮助

4

5 回答 5

14

我使用您的代码创建了简单的查询。你可以像使用它 -

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
于 2013-08-07T21:07:36.573 回答
14

您可以创建表值函数

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
于 2013-08-08T08:53:43.820 回答
7

此语法适用于外部别名:

  -- 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
)
于 2015-12-07T11:22:13.257 回答
6

首先删除第二个 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 恰好有两列。如果要从基础查询返回所有列并且这些名称是唯一的,则这些列是可选的。如果您的列多于或少于选择的列,则需要指定名称。

这是另一个例子:

桌子:

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 的列名。

结果:

在此处输入图像描述

于 2013-08-07T20:59:30.917 回答
2

对于仍在为此苦苦挣扎的任何人,您唯一需要做的就是在 CTE 之前用分号终止变量声明。没有其他要求。

DECLARE @test AS INT = 42;
WITH x 
     AS (SELECT @test AS 'Column') 

SELECT * 
FROM   x 

结果:

Column
-----------
42

(1 row affected)
于 2019-01-17T17:43:01.487 回答