web-dev-qa-db-fra.com

SQL Server POUR CHAQUE boucle

J'ai la requête SQL suivante:

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

Cela retourne naturellement '1/1/2010'.

Ce que je veux faire, c'est avoir une liste de dates, disons:

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

Ensuite, je veux POUR CHACUN à travers les nombres et exécuter la requête SQL.

Quelque chose comme (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

Donc, ceci retournerait: -

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

Je souhaite que cette opération renvoie les données sous la forme d'un ensemble de résultats, et non de plusieurs ensembles de résultats. Il est donc possible que je devrais utiliser une sorte d'union à la fin de la requête. Ainsi, chaque itération des unions de boucles passe à la suivante.

modifier

J'ai une requête volumineuse qui accepte un paramètre 'to date', je dois l'exécuter 24 fois, chaque fois avec une date spécifique que je dois pouvoir fournir (ces dates vont être dynamiques). Je veux éviter répéter 24 fois ma requête, tous les syndicats les rejoignant, comme si je devais revenir et ajouter des colonnes supplémentaires, cela prendrait beaucoup de temps.

56
JsonStatham

Le langage SQL est principalement un langage orienté sur les ensembles - il est généralement déconseillé d’utiliser une boucle dans ce langage.

Dans ce cas, un résultat similaire pourrait être obtenu en utilisant un CTE récursif:

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
59
user359040

Voici une option avec une variable de table:

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

Vous pouvez faire la même chose avec une table temporaire:

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

Vous devriez nous dire quel est votre objectif principal, comme l'a dit @JohnFx, cela pourrait probablement être fait d'une autre manière (plus efficace).

30
Lamak

Vous pouvez utiliser une table de variables, comme ceci:

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
14
Steve Mayne

Cela dépend de ce que vous voulez faire avec les résultats. Si vous êtes juste après les nombres, une option basée sur un ensemble serait un tableau des nombres - ce qui est pratique pour toutes sortes de choses.

Pour MSSQL 2005+, vous pouvez utiliser un CTE récursif pour générer un tableau de nombres en ligne:

;WITH Numbers (N) AS (
    SELECT 1 UNION ALL
    SELECT 1 + N FROM Numbers WHERE N < 500 
)
SELECT N FROM Numbers
OPTION (MAXRECURSION 500)
6
Mark Brackett
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
younes

Bien sûr une vieille question. Mais j'ai une solution simple où pas besoin de Looping, CTE, tableau de variables, 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

Remarque:spt_values est la table non documentée de Mircrosoft. Il a des numéros pour chaque type. Son utilisation n’est pas envisageable car elle peut être supprimée dans n’importe quelle nouvelle version de SQL Server sans information préalable, car elle n’est pas documentée. Mais nous pouvons l'utiliser comme solution de contournement rapide dans certains scénarios, comme ci-dessus.

2
Shakeer Mirza
[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
user3702431