SQL Server FOR EACH循环

时间:2012-04-24 14:49:53

标签: sql sql-server tsql

我有以下SQL查询:

DECLARE @MyVar datetime = '1/1/2010'    
SELECT @MyVar

这自然会回归' 1/1/2010'。

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

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

然后我希望通过数字进行每次运行并运行SQL查询。

像(伪代码):

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

所以这会回来: -

1/1/2010     2/1/2010     3/1/2010     4/1/2010     2010年5月1日

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

修改

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

7 个答案:

答案 0 :(得分: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

答案 1 :(得分: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

您可以对临时表执行相同的操作:

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

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

答案 2 :(得分:13)

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

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

答案 3 :(得分:6)

这取决于你想要的结果。如果您只是在数字之后,基于集合的选项将是numbers table - 这对于各种各样的事情都很方便。

对于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)

答案 4 :(得分: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

答案 5 :(得分:2)

当然是一个老问题。但我有一个简单的解决方案,不需要循环,CTE,表变量等。

DECLARE @MyVar datetime = '1/1/2010'    
SELECT @MyVar

SELECT DATEADD (DD,NUMBER,@MyVar) 
FROM master.dbo.spt_values 
WHERE TYPE='P' AND NUMBER BETWEEN 0 AND 4 
ORDER BY NUMBER

注意: spt_values是Mircrosoft的无证表。它有各种类型的数字。它不能被使用,因为它可以在没有事先信息的任何新版本的sql server中删除,因为它没有文档。但我们可以在某些情况下将其用作快速解决方法。

答案 6 :(得分:1)

[CREATE PROCEDURE [rat].[GetYear]

AS
BEGIN

-- variable for storing start date
Declare @StartYear as int
-- Variable for the End date 
Declare @EndYear as int 

-- Setting the value in strat Date
select @StartYear = Value from   rat.Configuration where Name = 'REPORT_START_YEAR'; 

-- Setting the End date 
select @EndYear = Value from   rat.Configuration where Name = 'REPORT_END_YEAR'; 


-- Creating Tem table 
    with [Years] as
    (
        --Selecting the Year
        select @StartYear [Year] 
        --doing Union 
        union all
         -- doing the loop in Years table 
         select Year+1 Year from [Years] where Year < @EndYear
     )
    --Selecting the Year table 
selec]