两个循环的SQL Server CTE增量函数?

时间:2014-05-21 14:56:13

标签: sql-server sql-server-2008 tsql

目前我在SQL Server 2008中有以下循环函数:

DECLARE @I int = 0
DECLARE @X int = 0
DECLARE @withdrawlCosntant float = 0.25
DECLARE @signups int = 0

WHILE @I<=12
BEGIN
  WHILE @X <= 24
  BEGIN
     SET @X = @X + 1

     SET @signups = (SELECT Singups FROM TraineeCredits WHERE I = @I AND X = @X)

     INSERT TraineeForecast(I, X, Signups)
     VALUES (@I, @X + 1, @signups - @singups * @withdrawlConstant)
  END

  SET @X = @I
  SET @I = @I + 1
END 
GO

虽然这有效,但对我来说速度极慢。

  • 我非常清楚如何使用种子和使用增量函数的UNION ALL在CTE中实现第一个循环,但我想知道是否可以在CTE中执行两个循环?
  • 我知道我可以使用execute()在循环中启动CTE。
  • 但是有没有办法在CTE中运行这样的两个增量函数?

编辑: 我如何创建一种推送行的方法? 基本上我和X就像一个轴中的轴。

我们有行:

(I,X,Signups) 
(0,1,2) 
(0,2,4) 
(0,3,1) 

我如何将其推下来为下一个I = 1?

(I,X,Signups) 
(1,1,0) 
(1,2,2) 
(1,3,4) 
(1,4,1) 

记住最大X为24.对于I = 2,它看起来像:

(I,X,Signups) 
(1,1,0) 
(1,2,0) 
(1,3,2) 
(1,4,4) 
(1,5,1) 

3 个答案:

答案 0 :(得分:1)

您不需要CTE。在数据库中创建Numbers表。 Numbers表只是一个表,其中包含从0到某个任意大数的连续整数的单个列(我的目标是9999)。将它留在数据库中,因为它对各种事物都很有用。

create table Numbers(Number int)
insert Numbers
SELECT TOP 10000 row_number() over(order by t1.number) -1 as N
FROM master..spt_values t1 
CROSS JOIN master..spt_values t2

现在您可以运行如下查询:

insert TraineeForecast(I, X, Signups)
select ni.Number I, nx.Number + 1 X, tc.Signups - tc.Signups * @withdrawlConstant Signups
from Numbers ni
cross join Numbers nx
left outer join TraineeCredits tc on tc.I = ni.Number and tc.X = nx.Number
where ni.Number between 0 and 12
and nx.Number between 1 and 24
and nx.Number > ni.Number

交叉连接为I和X的每个组合生成一个结果,可以将它们连接到您的TraineeCredits表以获得注册。

在此处查看SQLFiddle:http://sqlfiddle.com/#!3/e6994/1

答案 1 :(得分:0)

你可以生成两个循环&#39;以这种方式递归cte:

WITH r AS (
    SELECT 1 AS n, 1 AS m
    UNION ALL
    SELECT CASE WHEN m<24 THEN n ELSE n+1 END, 
        CASE WHEN m<24 THEN m+1 ELSE 1 end  
        FROM r WHERE n*m<288
)
SELECT * FROM r
OPTION (MAXRECURSION 0)

答案 2 :(得分:0)

事实上,您可以通过CTE实现数据插入。

WITH i_values as
  (
    SELECT 0 as i
    UNION ALL
    SELECT i_values.i+1
    FROM i_values
    WHERE i_values.i <= 11
  ),
x_values as
  (
    SELECT 0 as x
    UNION ALL
    SELECT x_values.x+1
    FROM x_values
    WHERE x_values.x <= 23
  )  
, i_x_values as
  (
    SELECT i_values.i, x_values.x
    FROM i_values
    FULL OUTER JOIN x_values
    ON x_values.x >= i_values.i - 1
  )
INSERT INTO TraineeForecast
SELECT i_x_values.I, (i_x_values.X)+1, TraineeCredits.Signups - TraineeCredits.Signups * 0.25
FROM TraineeCredits
INNER JOIN i_x_values
ON TraineeCredits.I = i_x_values.I AND TraineeCredits.X = i_x_values.X;

这是 SQL Fiddle demo