Easiest way to populate a temp table with dates between and including 2 date parameters

前端 未结 8 1623
旧时难觅i
旧时难觅i 2020-11-27 06:34

What is the easiest way to populate a temp table with dates including and between 2 date parameters. I only need the 1st day of the month dates.

So for example if @S

相关标签:
8条回答
  • 2020-11-27 06:36

    Interestingly, it is faster to create from enumerated data as per this article.

    DECLARE @StartDate DATE = '10001201';
    DECLARE @EndDate DATE   = '20000101';
    
    DECLARE @dim TABLE ([date] DATE)
    
    INSERT @dim([date])
    SELECT d
    FROM
    (
      SELECT
          d = DATEADD(DAY, rn - 1, @StartDate)
      FROM 
      (
          SELECT TOP (DATEDIFF(DAY, @StartDate, @EndDate)) 
              rn = ROW_NUMBER() OVER (ORDER BY s1.[object_id])
          FROM
              sys.all_objects AS s1
          CROSS JOIN
              sys.all_objects AS s2
          ORDER BY
              s1.[object_id]
      ) AS x
    ) AS y;
    

    On my machine, it's around 60% faster with large date ranges. The recursion method can populate 2000 years worth of data in around 3 seconds though, and looks a lot nicer, so I don't really recommend this method just for incrementing days.

    0 讨论(0)
  • 2020-11-27 06:48
    declare @StartDate datetime
    declare @EndDate datetime
    select @StartDate = '2011-01-01' ,  @EndDate = '2011-08-01'
    
    select @StartDate= @StartDate-(DATEPART(DD,@StartDate)-1)
    
    declare @temp  table
    (
    TheDate datetime
    )
    while (@StartDate<=@EndDate)
    begin
    insert into @temp
    values (@StartDate )
    select @StartDate=DATEADD(MM,1,@StartDate)
    end
    select * from @temp
    

    Works even if the @StartDate is not the first day of the month by going back to the initial day of the month of StartDate

    0 讨论(0)
  • 2020-11-27 06:50
    declare @StartDate date = '2014-01-01';
    declare @EndDate date = '2014-05-05';
    
    ;WITH cte AS (
        SELECT @StartDate AS myDate
        UNION ALL
        SELECT DATEADD(day,1,myDate) as myDate
        FROM cte
        WHERE DATEADD(day,1,myDate) <=  @EndDate
    )
    SELECT myDate
    FROM cte
    OPTION (MAXRECURSION 0)
    
    0 讨论(0)
  • 2020-11-27 06:50

    Solution:

    DECLARE  @StartDate DATETIME
            ,@EndDate DATETIME;
    
    SELECT   @StartDate = '20110105'
            ,@EndDate = '20110815';
    
    SELECT  DATEADD(MONTH, DATEDIFF(MONTH, 0, DATEADD(MONTH, v.number, @StartDate)), 0) AS FirstDay
    --or Andriy M suggestion:
    --SELECT    DATEADD(MONTH, DATEDIFF(MONTH, 0, @StartDate) + v.number, 0) AS FirstDay
    INTO    #Results
    FROM    master.dbo.spt_values v
    WHERE   v.type = 'P'        
    AND     DATEDIFF(MONTH, @StartDate, @EndDate) >= v.number;
    
    SELECT  *
    FROM    #Results;
    
    DROP TABLE #Results;
    

    Results:

    FirstDay
    -----------------------
    2011-01-01 00:00:00.000
    2011-02-01 00:00:00.000
    2011-03-01 00:00:00.000
    2011-04-01 00:00:00.000
    2011-05-01 00:00:00.000
    2011-06-01 00:00:00.000
    2011-07-01 00:00:00.000
    2011-08-01 00:00:00.000
    
    0 讨论(0)
  • 2020-11-27 06:59

    This works even if the @StartDate is not the first of the month. I'm assuming that if it's not the start of the month, you want to begin with the first of the next month. Otherwise remove the +1.:

    ;WITH cte AS (
    SELECT CASE WHEN DATEPART(Day,@StartDate) = 1 THEN @StartDate 
                ELSE DATEADD(Month,DATEDIFF(Month,0,@StartDate)+1,0) END AS myDate
    UNION ALL
    SELECT DATEADD(Month,1,myDate)
    FROM cte
    WHERE DATEADD(Month,1,myDate) <=  @EndDate
    )
    SELECT myDate
    FROM cte
    OPTION (MAXRECURSION 0)
    
    0 讨论(0)
  • 2020-11-27 06:59
    CREATE TABLE #t (d DATE)
    
    INSERT INTO #t SELECT GETDATE()
    
    GO
    
    INSERT #t SELECT DATEADD(DAY, -1, MIN(d)) FROM #t
    
    GO 10
    
    0 讨论(0)
提交回复
热议问题