简体   繁体   English

SQL Server FOR EACH循环

[英]SQL Server FOR EACH Loop

I have the following SQL query: 我有以下SQL查询:

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

This naturally returns '1/1/2010'. 这自然会返回'2010年1月1日'。

What I want to do is have a list of dates, say: 我想要做的是有一个日期列表,比如说:

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

Then i want to FOR EACH through the numbers and run the SQL Query. 然后我想通过数字FOR FOR EACH并运行SQL Query。

Something like (pseudocode): 像(伪代码)的东西:

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

So this would return:- 所以这会回来: -

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

I want this to return the data as one resultset, not multiple resultsets, so I may need to use some kind of union at the end of the query, so each iteration of the loop unions onto the next. 我希望这将数据作为一个结果集而不是多个结果集返回,因此我可能需要在查询结束时使用某种联合,因此循环的每次迭代都会联合到下一个结果集。

edit 编辑

I have a large query that accepts a 'to date' parameter, I need to run it 24 times, each time with a specific to date which I need to be able to supply (these dates are going to be dynamic) I want to avoid repeating my query 24 times with union alls joining them as if I need to come back and add additional columns it would be very time consuming. 我有一个接受'到期'参数的大型查询,我需要运行24次,每次都需要能够提供特定的日期(这些日期将是动态的)我想避免使用union alls重复我的查询24次,就好像我需要回来添加额外的列一样,这将是非常耗时的。

SQL is primarily a set-orientated language - it's generally a bad idea to use a loop in it. SQL主要是一种面向集合的语言 - 在其中使用循环通常是一个坏主意。

In this case, a similar result could be achieved using a recursive CTE: 在这种情况下,使用递归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

Here is an option with a table variable: 这是一个带有表变量的选项:

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

You can do the same with a temp table: 您可以使用临时表执行相同操作:

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

You should tell us what is your main goal, as was said by @JohnFx, this could probably be done another (more efficient) way. 您应该告诉我们您的主要目标是什么,正如@JohnFx所说,这可能是另一种(更有效)的方式。

You could use a variable table, like this: 您可以使用变量表,如下所示:

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

This kind of depends on what you want to do with the results. 这种取决于你想要对结果什么。 If you're just after the numbers, a set-based option would be a numbers table - which comes in handy for all sorts of things. 如果您只是在数字之后,基于集合的选项将是一个数字表 - 它可以用于各种各样的事情。

For MSSQL 2005+, you can use a recursive CTE to generate a numbers table inline: 对于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)
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

Off course an old question. 当然是一个老问题。 But I have a simple solution where no need of Looping, CTE, Table variables etc. 但我有一个简单的解决方案,不需要循环,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

Note : spt_values is a Mircrosoft's undocumented table. 注意: spt_values是Mircrosoft的未记录表。 It has numbers for every type. 它有各种类型的数字。 Its not suggestible to use as it can be removed in any new versions of sql server without prior information, since it is undocumented. 它不能被使用,因为它可以在没有事先信息的任何新版本的sql server中删除,因为它没有文档。 But we can use it as quick workaround in some scenario's like above. 但是我们可以在某些情况下将其用作快速解决方法,如上所述。

[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]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM