SQL Server FOR EACH循环

Jso*_*ham 58 sql t-sql sql-server

我有以下SQL查询:

DECLARE @MyVar datetime = '1/1/2010'    
SELECT @MyVar
Run Code Online (Sandbox Code Playgroud)

这自然会返回'2010年1月1日'.

我想要做的是有一个日期列表,比如说:

1/1/2010
2/1/2010
3/1/2010
4/1/2010
5/1/2010
Run Code Online (Sandbox Code Playgroud)

然后我想通过数字FOR FOR EACH并运行SQL Query.

像(伪代码)的东西:

List = 1/1/2010,2/1/2010,3/1/2010,4/1/2010,5/1/2010

For each x in List
do
  DECLARE @MyVar datetime = x

  SELECT @MyVar
Run Code Online (Sandbox Code Playgroud)

所以这会回来: -

1/1/2010 2/1/2010 3/1/2010 4/1/2010 5/1/2010

我希望这将数据作为一个结果集而不是多个结果集返回,因此我可能需要在查询结束时使用某种联合,因此循环的每次迭代都会联合到下一个结果集.

编辑

我有一个接受'到期'参数的大型查询,我需要运行24次,每次都需要能够提供特定的日期(这些日期将是动态的)我想避免使用union alls重复我的查询24次,就好像我需要回来添加额外的列一样,这将是非常耗时的.

小智 59

SQL主要是一种面向集合的语言 - 在其中使用循环通常是一个坏主意.

在这种情况下,使用递归CTE可以实现类似的结果:

with cte as
(select 1 i union all
 select i+1 i from cte where i < 5)
select dateadd(d, i-1, '2010-01-01') from cte
Run Code Online (Sandbox Code Playgroud)

  • `i`的最大步长限制为100,等于最大递归限制.尝试`...来自CTE,其中i <= 101`或者通过`OPTION(MAXRECURSION 500)增加递归限制 (7认同)
  • 我是唯一一个不理解这个公认答案的人吗? (5认同)

Lam*_*mak 30

这是一个带有表变量的选项:

DECLARE @MyVar TABLE(Val DATETIME)
DECLARE @I INT, @StartDate DATETIME
SET @I = 1
SET @StartDate = '20100101'

WHILE @I <= 5
BEGIN
    INSERT INTO @MyVar(Val)
    VALUES(@StartDate)

    SET @StartDate = DATEADD(DAY,1,@StartDate)
    SET @I = @I + 1
END
SELECT *
FROM @MyVar
Run Code Online (Sandbox Code Playgroud)

您可以使用临时表执行相同操作:

CREATE TABLE #MyVar(Val DATETIME)
DECLARE @I INT, @StartDate DATETIME
SET @I = 1
SET @StartDate = '20100101'

WHILE @I <= 5
BEGIN
    INSERT INTO #MyVar(Val)
    VALUES(@StartDate)

    SET @StartDate = DATEADD(DAY,1,@StartDate)
    SET @I = @I + 1
END
SELECT *
FROM #MyVar
Run Code Online (Sandbox Code Playgroud)

您应该告诉我们您的主要目标是什么,正如@JohnFx所说,这可能是另一种(更有效)的方式.


Ste*_*yne 14

您可以使用变量表,如下所示:

declare @num int

set @num = 1

declare @results table ( val int )

while (@num < 6)
begin
  insert into @results ( val ) values ( @num )
  set @num = @num + 1
end

select val from @results
Run Code Online (Sandbox Code Playgroud)


Mar*_*ett 6

这种取决于你想要对结果什么.如果您只是在数字之后,基于集合的选项将是一个数字表 - 它可以用于各种各样的事情.

对于MSSQL 2005+,您可以使用递归CTE生成内联数字表:

;WITH Numbers (N) AS (
    SELECT 1 UNION ALL
    SELECT 1 + N FROM Numbers WHERE N < 500 
)
SELECT N FROM Numbers
OPTION (MAXRECURSION 500)
Run Code Online (Sandbox Code Playgroud)


小智 5

declare @counter as int
set @counter = 0
declare @date as varchar(50)
set @date = cast(1+@counter as varchar)+'/01/2013'
while(@counter < 12)
begin 
select  cast(1+@counter as varchar)+'/01/2013' as date
set @counter = @counter + 1
end
Run Code Online (Sandbox Code Playgroud)