【问题标题】:Get start and end dates of month in between two dates in SQL?在 SQL 中的两个日期之间获取月份的开始日期和结束日期?
【发布时间】:2013-02-10 22:19:09
【问题描述】:

我有以下函数,它应该返回两个月之间月份的开始日期和结束日期,但问题是,由于本月是 28 天,因此该函数正在计算 28 天内所有即将到来的月份基础因此返回以下错误值。

StartDate   EndDate
-----------------------   
2013-02-01  2013-02-28 
2013-03-01  2013-03-28 
2013-04-01  2013-04-28 



declare @sDate datetime,
        @eDate datetime;

select  @sDate = '2013-02-25',
        @eDate = '2013-04-25';

;with months as
(
  select DATEADD(mm,DATEDIFF(mm,0,@sDate),0) StartDate, 
  DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,@sDate)+1,0)) EndDate

  union all
  select dateadd(mm, 1, StartDate),
    dateadd(mm, 1, EndDate)
  from months
  where dateadd(mm, 1, StartDate)<=  @eDate
)

select * from months

如何修改它以返回正确的日期?

【问题讨论】:

  • 您不应该使用包容性上限 - 您应该说“小于下个月的开始”。这是考虑日期/时间/时间戳值的错误方法,apparently SQL Server has a unique set of problems 也在处理这个问题。因此,获取月初,添加一个月,并使用包含下限 (&gt;=) 和独占上限 (&lt;)。

标签: sql sql-server


【解决方案1】:

如果您可以获取该月的第一天,请使用两次dateadd 获取最后一天。

先加 1 个月,再减 1 天。

【讨论】:

    【解决方案2】:

    试试这个;

    declare @sDate datetime,
            @eDate datetime
    
    select  @sDate = '2013-02-25',
            @eDate = '2013-04-25'
    
    ;with cte as (
      select convert(date,left(convert(varchar,@sdate,112),6) + '01') startDate,
             month(@sdate) n
      union all
      select dateadd(month,n,convert(date,convert(varchar,year(@sdate)) + '0101')) startDate,
            (n+1) n
      from cte
      where n < month(@sdate) + datediff(month,@sdate,@edate)
    )
    select startdate, dateadd(day,-1,dateadd(month,1,startdate)) enddate
    from cte
    

    FIDDLE DEMO

    |  STARTDATE |    ENDDATE |
    ---------------------------
    | 2013-02-01 | 2013-02-28 |
    | 2013-03-01 | 2013-03-31 |
    | 2013-04-01 | 2013-04-30 |
    

    【讨论】:

    • 你能评论代码并解释它的作用吗,谢谢
    【解决方案3】:

    试试这个:这是一个表函数。返回包含部分日期的月份开始和结束日期表。

        CREATE FUNCTION [dbo].[Fun_GetFirstAndLastDateOfeachMonth] (
              @StartDate  DATE,
              @EndDate DATE
        )
    
        RETURNS @Items TABLE (
              StartDate DATE ,EndDate DATE,MonthNumber INT,YearNumber INT
        )
    
        AS
        BEGIN
                ;WITH cte AS (
                  SELECT CONVERT(DATE,LEFT(CONVERT(VARCHAR,@StartDate,112),6) + '01') startDate,
                         MONTH(@StartDate) n
                  UNION ALL
                  SELECT DATEADD(MONTH,N,CONVERT(DATE,CONVERT(VARCHAR,YEAR(@StartDate)) + '0101')) startDate,
                        (n+1) n
                  FROM cte
                  WHERE n < MONTH(@StartDate) + DATEDIFF(MONTH,@StartDate,@EndDate)
                )
                INSERT INTO @Items
                SELECT  CASE WHEN  MONTH(startdate) = MONTH(@StartDate) THEN @StartDate ELSE startdate END AS StartDate, 
                CASE WHEN  MONTH(startdate) = MONTH(@EndDate) THEN @EndDate ELSE DATEADD(DAY,-1,DATEADD(MONTH,1,startdate)) END AS  enddate,
                MONTH(startDate) AS MonthNumner,YEAR(startDate) AS YearNumber
                FROM cte
    
              RETURN
    
        END -- End Function
    

    创建函数后执行此操作

    SELECT * From [EDDSDBO].[Fun_GetFirstAndLastDateOfeachMonth] ('2019-02-25','2019-05-20')
    

    【讨论】:

      【解决方案4】:

      您可以使用下面的代码

      create FUNCTION [dbo].fn_getfirstandenddate (
            @StartDate  DATE,
            @EndDate DATE
      )
      RETURNS @Items TABLE (
            StartDate DATE ,EndDate DATE
      )AS
      BEGIN
      insert into @ItemsSELECT case when @startdate > DATEADD(DAY,1,EOMONTH((DATEADD(MONTH, x.number, @StartDate)),-1)) then @startdate else DATEADD(DAY,1,EOMONTH((DATEADD(MONTH, x.number, @StartDate)),-1)) end startDay,case when @enddate < eomonth(DATEADD(MONTH, x.number, @StartDate)) then @enddate else eomonth(DATEADD(MONTH, x.number, @StartDate)) end endDate FROM    master.dbo.spt_values x WHERE   x.type = 'P'AND     x.number <= DATEDIFF(MONTH, @StartDate, @EndDate);
      
            RETURN
      
      END 
      

      【讨论】:

        猜你喜欢
        • 2020-12-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-01-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-05-29
        相关资源
        最近更新 更多