【问题标题】:How can I increment a variable inside a CTE recursion with SQL Server 2008如何使用 SQL Server 2008 在 CTE 递归中增加变量
【发布时间】:2018-05-23 03:56:57
【问题描述】:

我有以下代码,我想用 CTE 进行递归并增加内部变量,以便递归可以使用它来执行子查询。

WITH cte as
(
    select @layer as layers,
    case when exists(select * from #table where layer=@layer and string in ('abc','xyz)) then 10 else 0 end 
    union all
    select layers + 1, total
    from cte
    where layers + 1<4 -- 4 is a max number that is unknown and given by the user
)select * from cte

#table的结构如下,但数据量是动态的

string     layer
abc        1
xyz        1
abc        2
xyz        2

所以在第 1 层,如果它有“abc”或“xyz”,它的点数为 10,第 2 层会发生同样的事情,直到用户给出的最大层。我想从递归中得到点和相应的级别。禁止循环和游标。我在递归中增加@layer 时遇到了麻烦。有什么建议吗?谢谢

【问题讨论】:

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


    【解决方案1】:

    我从未见过递归中使用的变量,但我认为您可以使用计数表来做您想做的事情。

    if object_id('tempdb..#table') is not null drop table #table
    
    create table #table (string varchar(64), layer int)
    insert into #table
    values
    ('abc',1),
    ('abc',2),
    ('xyz',2),
                --missing layer 3
                --missing layer 4
    ('fgh',5),  --not in the abc or xyz clause
    ('abc',6),
    ('xyz',7)   --greate than the max passed in via @layer
    
    
    
    
    declare @layer int = 6
    
    ;WITH
        E1(N) AS (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)),
        E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
        E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max
        cteTally(N) AS 
        (
            SELECT  ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4
        )
    
    select
        N as Layer
        ,case when max(layer) is not null then 10 else 0 end
    from 
        cteTally
        full join #table 
        on N = layer and string in ('abc','xyz')
    where N <= @layer
    group by N
    order by N
    

    如果你真的打算使用递归,如果传入的@layer 或 max 数量很大,这可能会慢很多,那么你将如何实现它。

    declare @layer int = 6
    
    ;with cte as(
        select 
            1 as layer
            ,total = case when exists(select * from #table t2 where t2.layer=layer and t2.string in ('abc','xyz')) then 10 else 0 end
        union all
        select 
            layer + 1
            ,total = case when exists(select * from #table t2 where t2.layer=c.layer + 1 and t2.string in ('abc','xyz')) then 10 else 0 end
        from cte c
        where layer < @layer)
    
    select distinct 
        layer
        ,total = max(total)
    from cte
    group by layer
    order by layer
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-12-13
      • 2020-06-08
      • 2012-04-23
      • 2014-05-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多