months between two dates in sql server with starting and end date of each of them in sql server

前端 未结 6 1450
误落风尘
误落风尘 2020-12-20 00:07

i want to get months between two dates with their starting and end dates.Suppose if i enter startdate as \"2017-04-01\" and enddate as \"2017-07-31\", i want list of months

6条回答
  •  既然无缘
    2020-12-20 00:34

    Without recursion, using master.dbo.spt_values as a substitute for a numbers table:

    declare @StartDate date = '20170401'
          , @EndDate   date = '20170731';
    ;with Months as (
      select top (datediff(month,@startdate,@enddate)+1) 
          [Month] = dateadd(month, row_number() over (order by number) -1, @StartDate)
        , MonthEnd = dateadd(day,-1,dateadd(month, row_number() over (order by number), @StartDate))
      from master.dbo.spt_values
      order by [Month]
    )
    select * from Months;
    

    rextester demo: http://rextester.com/FXQJ4048

    returns:

    +------------+------------+
    |   Month    |  MonthEnd  |
    +------------+------------+
    | 2017-04-01 | 2017-04-30 |
    | 2017-05-01 | 2017-05-31 |
    | 2017-06-01 | 2017-06-30 |
    | 2017-07-01 | 2017-07-31 |
    +------------+------------+
    

    When generating a set or sequence in SQL Server, methods that avoid recursion and loops perform significantly better as the number of values increases.

    Reference:

    • Generate a set or sequence without loops - 1 - Aaron Bertrand
    • Generate a set or sequence without loops - 2 - Aaron Bertrand
    • Generate a set or sequence without loops - 3 - Aaron Bertrand

    To get the start and end dates of each month within a given range, when the value of the @StartDate parameter is not the first day of the month:

    The first option is to truncate the @StartDate parameter to the first of the month, the second option is to adjust the expressions in the common table expression to truncate the values there:

    declare @StartDate date = '20170415'
          , @EndDate   date = '20170715';
    /* Option 1: truncate @StartDate to the beginning of the month */
    --set @StartDate = dateadd(month, datediff(month, 0, @StartDate), 0);
    /* Option 2: Truncate @StartDate to month in the common table expression: */
    ;with Months as (
    select top (datediff(month,@StartDate,@EndDate)+1) 
        [Month] = dateadd(month
                   , datediff(month, 0, @StartDate) + row_number() over (order by number) -1
                   , 0)
        , MonthEnd = dateadd(day,-1,dateadd(month
                   , datediff(month, 0, @StartDate) + row_number() over (order by number) 
                   ,0))
      from master.dbo.spt_values
      order by [Month]
    )
    select * from Months;
    

提交回复
热议问题