SQL Server PARA CADA Bucle


Tengo la siguiente consulta SQL:

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

Esto, naturalmente, devuelve '1/1/2010'.

Lo que quiero hacer es tener una lista de fechas, digamos:

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

Entonces quiero PARA CADA uno a través de los números y ejecutar la consulta SQL.

Algo así como (pseudocódigo):

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

Así que esto regresaría: -

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

Quiero que esto devuelva los datos como un conjunto de resultados, no varios conjuntos de resultados, por lo que puede que necesite usar algún tipo de unión al final de la consulta, por lo que cada iteración del bucle se une al siguiente.

Editar

Tengo una consulta grande que acepta un parámetro 'to date', necesito ejecutarlo 24 veces, cada vez con una fecha específica que necesito poder suministrar (estas fechas van a ser dinámicas) Quiero evitar repetir mi consulta 24 veces con union alls uniéndolas como si tuviera que volver y agregar columnas adicionales sería muy lento.

Author: Luke Girvin, 2012-04-24

7 answers

SQL es principalmente un lenguaje orientado a conjuntos-generalmente es una mala idea usar un bucle en él.

En este caso, se podría lograr un resultado similar usando un CTE recursivo:

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
 55
Author: Josef K,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-29 08:59:55

Aquí hay una opción con una variable de tabla:

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

Puedes hacer lo mismo con una tabla temporal:

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

Deberías decirnos cuál es tu objetivo principal, como dijo @JohnFx, esto probablemente podría hacerse de otra manera (más eficiente).

 28
Author: Lamak,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-04-24 15:22:23

Podría usar una tabla de variables, como esta:

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
 13
Author: Steve Mayne,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-02-16 21:46:41

Este tipo de depende de lo que desea hacer con los resultados. Si estás justo después de los números, una opción basada en conjuntos sería una tabla de números , que es útil para todo tipo de cosas.

Para MSSQL 2005+, puede usar un CTE recursivo para generar una tabla de números en línea:

;WITH Numbers (N) AS (
    SELECT 1 UNION ALL
    SELECT 1 + N FROM Numbers WHERE N < 500 
)
SELECT N FROM Numbers
OPTION (MAXRECURSION 500)
 6
Author: Mark Brackett,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-04-24 14:57:21
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
Author: younes,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-09-06 18:40:33
[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]
 1
Author: Soner Gönül,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-03-19 12:39:17

Por supuesto una vieja pregunta. Pero tengo una solución simple donde no hay necesidad de bucle, CTE, variables de tabla, etc.

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
 1
Author: Shakeer Mirza,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-24 06:58:03