Program Tip

SQL Server FOR EACH 루프

programtip 2020. 12. 15. 19:43
반응형

SQL Server FOR EACH 루프


다음 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

따라서 다음과 같이 반환됩니다.

2010 년 1 월 1 일 2010 년 2 월 1 일 2010 년 3 월 1 일 2010 년 4 월 1 일 2010 년 5 월 1 일

여러 결과 집합이 아닌 하나의 결과 집합으로 데이터를 반환하기를 원하므로 쿼리 끝에 일종의 통합을 사용해야 할 수 있으므로 루프의 각 반복이 다음으로 통합됩니다.

편집하다

'to date'매개 변수를 허용하는 큰 쿼리가 있습니다. 24 번 실행해야합니다. 매번 제공 할 수 있어야하는 특정 to date (이 날짜는 동적 일 것입니다)를 사용하여 실행해야합니다. 다시 돌아와서 추가 열을 추가해야하는 것처럼 통합 모두를 결합하여 내 쿼리를 24 번 반복하면 시간이 많이 걸립니다.


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

다음은 테이블 변수가있는 옵션입니다.

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가 말했듯이 주요 목표가 무엇인지 알려 주셔야합니다. 이것은 아마도 다른 (보다 효율적인) 방법으로 수행 될 수 있습니다.


다음과 같이 변수 테이블을 사용할 수 있습니다.

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

이러한 종류 는 결과 수행 하려는 작업 에 따라 다릅니다 . 숫자 바로 뒤에있는 경우 집합 기반 옵션은 모든 종류의 항목에 편리하게 사용할 수있는 숫자 테이블 입니다.

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

물론 오래된 질문입니다. 하지만 루프, 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. 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. 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]

ReferenceURL : https://stackoverflow.com/questions/10300414/sql-server-for-each-loop

반응형