【问题标题】:SQL Server : CTE (recursion), set condition outside the CTESQL Server:CTE(递归),在 CTE 之外设置条件
【发布时间】:2014-01-30 18:50:06
【问题描述】:

使用下面的查询(我是 CTE 新手,所以这可能会很混乱),我想为我的数据库中的所有最终类别构建一个反向类别路径。

目前,我在 CTE 本身 (268707) 中定义了一个 ID。在我的最终主查询期间,有没有办法在我引用 CTE 时提供一个变量?

我在查询中添加了一条评论,我认为这是执行此操作的理想位置,但对于我的生活而言,我无法弄清楚如何。

WITH recursion(stocknode_id, short_desc, parentnode_id, level) AS
(
SELECT
    stocknode_id,
    short_desc,
    parentnode_id,
    0 AS level

FROM stock_website_node AS swn

WHERE swn.stocknode_id = 268707

UNION ALL

SELECT
    swn.stocknode_id,
    swn.short_desc,
    swn.parentnode_id,
    h.level + 1

FROM stock_website_node AS swn

INNER JOIN recursion AS h ON h.parentnode_id = swn.stocknode_id
)

SELECT
TOP 1 STUFF
(
    (
        SELECT ' / ' + swn_stuff.short_desc
        FROM stock_website_node AS swn_stuff
        WHERE swn_stuff.stocknode_id IN (SELECT stocknode_id FROM recursion) /* <--- I want to pass the variable from here, I think... */
        FOR XML PATH(''), TYPE
    ).value('.','varchar(max)'),
    1, 2, ''
 ) AS category_tree

FROM stock_website_node AS swn_a

如果我也要做类似的事情(但似乎不起作用),我最理想的情况是会产生结果:

WITH recursion(stocknode_id, short_desc, parentnode_id, level) AS
(
    SELECT
        stocknode_id,
        short_desc,
        parentnode_id,
        0 AS level

    FROM stock_website_node AS swn

    UNION ALL

    SELECT
        swn.stocknode_id,
        swn.short_desc,
        swn.parentnode_id,
        h.level + 1

    FROM stock_website_node AS swn

    INNER JOIN recursion AS h ON h.parentnode_id = swn.stocknode_id
)

SELECT
    TOP 1 STUFF
    (
        (
            SELECT ' / ' + swn_stuff.short_desc
            FROM stock_website_node AS swn_stuff
            WHERE swn_stuff.stocknode_id IN (SELECT x.stocknode_id FROM recursion AS x WHERE x.xtocknode_id = swn_a.stocknode_id)
            FOR XML PATH(''), TYPE
        ).value('.','varchar(max)'),
        1, 2, ''
     ) AS category_tree

FROM stock_website_node AS swn_a

WHERE swn_a = 268707 OR swn_a = 268708 OR swn_a = 268709

我已经使用 SQL 创建了一个键盘来创建一个表变量,因此如果您想运行代码 (http://codepad.org/4AaZEnlq),您可以准确地看到我在做什么。

表中保存了类别,parentnode_id指的是父类别的stocknode_id。 parentnode_id 为 0 表示这是顶级类别。 CTE中当前提供的变量是底层类别,查询整体构建一个类别路径作为结果,如:

顶级/二级/三级/四级

在主查询期间,我想提供几个底层类别并返回每个类别的类别路径,但目前只能手动定义一个底层 ID 而不是动态提供几个,我是有点卡住了。

【问题讨论】:

  • 当然,您拥有与任何其他查询相同的选项。

标签: sql sql-server-2008 recursion common-table-expression


【解决方案1】:

将 CTE 中的常量值替换为变量,并在执行查询之前为变量赋值。

您不能将值从您在代码中注释的位置传递给 CTE。该值必须在整个查询之前分配给变量。

declare @v int;
set @v = 268707;

with ....
(
  select ...
  where swn.stocknode_id = @v
  union all
  select ...
)
select ...

如果你想指定多个 stocknode_id,你可以添加一个表变量来保存你需要的值,并在这样的查询中使用它:

declare @T table(stocknode_id int);
insert into @T values(8), (12);

with R as 
(
  select C.stocknode_id, 
         cast(C.short_desc as varchar(max)) as short_desc,
         C.parentnode_id
  from @categories as C
  where C.stocknode_id in (select T.stocknode_id from @T as T)
  union all
  select C.stocknode_id,
         C.short_desc + ' / ' +  R.short_desc,
         C.parentnode_id
  from @categories as C
    inner join R  
      on C.stocknode_id = R.parentnode_id
)
select R.short_desc
from R
where R.parentnode_id = 0;

SQL Fiddle

【讨论】:

  • 我在从swn_a 中选择时尝试使用变量,但出现错误:A SELECT statement that assigns a value to a variable must not be combined with data-retrieval operations.
  • 您应该在执行查询之前将值分配给变量
  • 啊,我的问题是我希望动态设置变量,即@var = swn_a.stocknode_id
  • @Ben,在您的第二个查询中,我想您可以将整个 where 子句移动到递归 CTE 的锚部分。如果不是,那么我真的不了解您的表结构以及您的查询是做什么的。如果您需要帮助将查询重写为可以工作并执行您想要的操作,您需要将表结构、示例数据和预期输出添加到问题中。
  • 我已经更新了我的问题,您可以在这里找到一个更好的表结构示例:codepad.org/4AaZEnlq - 感谢您的帮助
猜你喜欢
  • 2011-10-20
  • 1970-01-01
  • 1970-01-01
  • 2017-08-31
  • 2016-01-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-24
相关资源
最近更新 更多