SQL Server для каждого цикла
у меня есть следующий 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
5/1/2010
Я хочу, чтобы это вернуть данные как один результирующий набор, а не несколько результирующих наборов, поэтому мне может потребоваться использовать какое-то объединение в конце запроса, поэтому каждая итерация объединения цикла на следующую.
edit
у меня есть большой запрос, который принимает параметр "to date", мне нужно запускать его 24 раза, каждый раз с определенной датой, которую мне нужно предоставить (эти даты будут динамическими) я хочу избежать повторения моего запроса 24 раза с объединением alls, присоединяющимся к ним, как будто мне нужно вернуться и добавить дополнительные столбцы было бы очень много времени.
7 ответов:
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
этот вид зависит от того, что вы хотите do С результатами. Если вы просто после чисел, параметр на основе набора будет таблица номеров - который пригодится для всех видов вещей.
для MSSQL 2005+ вы можете использовать рекурсивный CTE для создания таблицы чисел inline:
;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
[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]
конечно старый вопрос. Но у меня есть простое решение, где нет необходимости в цикле, 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
Comments