【问题标题】:Calculating number of full months between two dates in SQL计算SQL中两个日期之间的整月数
【发布时间】:2009-07-09 23:22:44
【问题描述】:

我需要计算SQL中的FULL月数,即

  • 2009-04-16 到 2009-05-15 => 0 整月
  • 2009-04-16 到 2009-05-16 => 1 个完整月
  • 2009-04-16 到 2009-06-16 => 2 个完整月

我尝试使用 DATEDIFF,即

SELECT DATEDIFF(MONTH, '2009-04-16', '2009-05-15')

但不是给我两个日期之间的整月,而是给我月份部分的差异,即

1

有人知道如何计算 SQL Server 中的整月数吗?

【问题讨论】:

  • 2009-01-31 至 2009-02-28。那是 0 个月还是 1 个月?

标签: sql sql-server


【解决方案1】:

原来的帖子有一些错误...所以我重新编写并将其打包为UDF。

CREATE FUNCTION FullMonthsSeparation 
(
    @DateA DATETIME,
    @DateB DATETIME
)
RETURNS INT
AS
BEGIN
    DECLARE @Result INT

    DECLARE @DateX DATETIME
    DECLARE @DateY DATETIME

    IF(@DateA < @DateB)
    BEGIN
        SET @DateX = @DateA
        SET @DateY = @DateB
    END
    ELSE
    BEGIN
        SET @DateX = @DateB
        SET @DateY = @DateA
    END

    SET @Result = (
                    SELECT 
                    CASE 
                        WHEN DATEPART(DAY, @DateX) > DATEPART(DAY, @DateY)
                        THEN DATEDIFF(MONTH, @DateX, @DateY) - 1
                        ELSE DATEDIFF(MONTH, @DateX, @DateY)
                    END
                    )

    RETURN @Result
END
GO

SELECT dbo.FullMonthsSeparation('2009-04-16', '2009-05-15') as MonthSep -- =0
SELECT dbo.FullMonthsSeparation('2009-04-16', '2009-05-16') as MonthSep -- =1
SELECT dbo.FullMonthsSeparation('2009-04-16', '2009-06-16') as MonthSep -- =2

【讨论】:

  • 是的,我知道这个答案现在已经超过 5 年了,但是我在谷歌搜索时遇到了它。这只有一个问题,在比较一个月的结束日时它会下降。 FullMonthsSeparation('2012-12-31', '2013-02-28') 返回 1,而不是 2。
  • 这是 OP 要求的行为。
  • 不需要只创建@result 部分的函数。例如:选择名称,(SELECT CASE WHEN DATEPART(DAY, '2016-08-28') > DATEPART(DAY, '2016-09-29') THEN DATEDIFF(MONTH, '2016-08-28', '2016 -09-29') - 1 ELSE DATEDIFF(MONTH, '2016-08-28', '2016-09-29') END) as NumberOfMonths FROM tableExample;
  • @Barett 那么如何更改函数返回 FullMonthSeparation('2012-12-31','2013'-2-28') 返回 2,而不是 1?
  • 这在 2019-01-31 和 2019-02-28 之间得到了错误的结果。答案应该是 1。但是这个函数返回 0
【解决方案2】:

你对一个月的定义是什么?从技术上讲,一个月可以是 28、29、30 或 31 天,具体取决于月份和闰年。

您似乎认为一个月是 30 天,因为在您的示例中您忽略了 May 有 31 天,那么为什么不直接执行以下操作?

SELECT DATEDIFF(DAY, '2009-04-16', '2009-05-15')/30
    , DATEDIFF(DAY, '2009-04-16', '2009-05-16')/30
    , DATEDIFF(DAY, '2009-04-16', '2009-06-16')/30

【讨论】:

  • 我认为 OP 想要回答的问题是:“在第一个日期通过第二个日期之前,我可以增加多少次?” (适当处理年份)
  • OP“无视 May 有 31 天”这一事实表明他确实认为一个月是 30 天
【解决方案3】:
select case when DATEPART(D,End_dATE) >=DATEPART(D,sTAR_dATE) 
THEN ( case when DATEPART(M,End_dATE) = DATEPART(M,sTAR_dATE) AND DATEPART(YYYY,End_dATE) = DATEPART(YYYY,sTAR_dATE) 
        THEN 0 ELSE DATEDIFF(M,sTAR_dATE,End_dATE)END )
ELSE DATEDIFF(M,sTAR_dATE,End_dATE)-1 END

【讨论】:

    【解决方案4】:

    这仅适用于 ORACLE,不适用于 SQL-Server:

    months_between(to_date ('2009/05/15', 'yyyy/mm/dd'), 
                   to_date ('2009/04/16', 'yyyy/mm/dd'))
    

    整月:

    round(months_between(to_date ('2009/05/15', 'yyyy/mm/dd'), 
                         to_date ('2009/04/16', 'yyyy/mm/dd')))
    

    可以在Oracle 8i及以上版本中使用。

    【讨论】:

      【解决方案5】:

      dateadd 函数可用于偏移到月初。如果 endDate 比 startDate 少了一天,它将被推到上个月,因此 datediff 将给出正确的月数。

      DATEDIFF(MONTH, DATEADD(DAY,-DAY(startDate)+1,startDate),DATEADD(DAY,-DAY(startDate)+1,endDate))
      

      【讨论】:

      • 虽然这段代码可能会回答这个问题,但最好在不介绍其他人的情况下解释如何它解决问题以及为什么要使用它。从长远来看,纯代码的答案没有用处。
      • 这似乎不适用于“2018 年 1 月 31 日”的开始日期和“2018 年 3 月 1 日”的结束日期,我得到一个 0
      【解决方案6】:

      我知道这是一个老问题,但只要日期 >= 01-Jan-1753 我使用:

      DATEDIFF(MONTH, DATEADD(DAY,-DAY(@Start)+1,@Start),DATEADD(DAY,-DAY(@Start)+1,@End))
      

      【讨论】:

        【解决方案7】:

        DATEDIFF() 旨在返回指定跨度的两个日期之间跨越的数字边界。为了让它做你想做的事,你需要做一个额外的调整,以考虑日期何时跨越边界但没有完成整个跨度。

        【讨论】:

          【解决方案8】:
          WITH   
          -- Count how many months must be added to @StartDate to exceed @DueDate  
          MONTHS_SINCE(n, [Month_hence], [IsFull], [RemainingDays] ) AS (  
          SELECT   
              1 as n,  
              DATEADD(Day, -1, DATEADD(Month, 1, @StartDate)) AS Month_hence  
              ,CASE WHEN (DATEADD(Day, -1, DATEADD(Month, 1, @StartDate)) <= @LastDueDate)   
                  THEN 1   
                  ELSE 0   
              END  AS [IsFull]  
              ,DATEDIFF(day, @StartDate,  @LastDueDate) as [RemainingDays]  
          UNION ALL  
          SELECT  
              n+1,  
              --DateAdd(Month, 1, Month_hence) as Month_hence -- No, causes propagation of short month discounted days  
              DATEADD(Day, -1, DATEADD(Month, n+1, @StartDate)) as Month_hence  
              ,CASE WHEN (DATEADD(Day, -1, DATEADD(Month, n+1, @StartDate)) <= @LastDueDate)   
                  THEN 1   
                  ELSE 0    
              END  AS [IsFull]  
              ,DATEDIFF(day, DATEADD(Day, -1, DATEADD(Month, n, @StartDate)),  @LastDueDate)  
              FROM MONTHS_SINCE   
              WHERE Month_hence<( @LastDueDate --WHERE Period= 1  
              )  
          ), --SELECT * FROM MONTHS_SINCE  
          MONTH_TALLY (full_months_over_all_terms, months_over_all_terms, days_in_incomplete_month ) AS (  
          SELECT  
              COALESCE((SELECT MAX(n) FROM MONTHS_SINCE WHERE isFull = 1),1) as full_months_over_all_terms,  
              (SELECT MAX(n) FROM MONTHS_SINCE ) as months_over_all_terms,  
              COALESCE((SELECT [RemainingDays] FROM MONTHS_SINCE WHERE isFull = 0),0) as days_in_incomplete_month  
          ) SELECT * FROM MONTH_TALLY;   
          

          【讨论】:

            【解决方案9】:

            仅@result 部分不需要创建函数。例如:

            Select Name,
            (SELECT CASE WHEN 
            DATEPART(DAY, '2016-08-28') > DATEPART(DAY, '2016-09-29')   
            THEN DATEDIFF(MONTH, '2016-08-28',  '2016-09-29') - 1
            ELSE DATEDIFF(MONTH, '2016-08-28',  '2016-09-29') END) as NumberOfMonths
            
            FROM 
            tableExample;
            

            【讨论】:

              【解决方案10】:

              此答案遵循 T-SQL 格式。我将此问题概念化为 datetime 格式的两个日期点之间的线性时间距离之一,称它们为 Time1 和 Time2; Time1 应与您正在处理的“较早的时间”值对齐(例如出生日期或小部件创建日期或旅程开始日期),并且 Time2 应与“较新的时间”值对齐(例如快照日期或小部件完成日期或旅程检查点到达日期)。

              DECLARE @Time1 DATETIME
              SET @Time1 = '12/14/2015'
              
              DECLARE @Time2 DATETIME
              SET @Time2 = '12/15/2016'
              

              该解决方案利用了对不同长度的多个周期的串行交叉点的简单测量、转换和计算;这里:世纪,十年,年,月,日(感谢玛雅日历的概念!)。简短的感谢信:感谢 Stack Overflow 的其他贡献者向我展示了我在此过程中拼接在一起的一些组件功能。我在这个论坛上对这些内容给予了积极评价。

              首先,构建一个地平线,它是 Century、Decade、Year、Month 周期的交点的线性集合,按月递增。为此使用交叉连接笛卡尔函数。 (将其视为创建布料,我们将在两个 'yyyy-mm' 点之间切割一段长度以测量距离):

              SELECT 
              Linear_YearMonths = (centuries.century + decades.decade + years.[year] + months.[Month]),
              1 AS value
              INTO #linear_months
              FROM
              (SELECT '18' [century] UNION ALL
              SELECT '19' UNION ALL
              SELECT '20') centuries 
              CROSS JOIN 
              (SELECT '0' [decade] UNION ALL
              SELECT '1' UNION ALL
              SELECT '2' UNION ALL
              SELECT '3' UNION ALL
              SELECT '4' UNION ALL
              SELECT '5' UNION ALL
              SELECT '6' UNION ALL
              SELECT '7' UNION ALL
              SELECT '8' UNION ALL
              SELECT '9') decades 
              CROSS JOIN 
              (SELECT '1' [year] UNION ALL
              SELECT '2' UNION ALL
              SELECT '3' UNION ALL
              SELECT '4' UNION ALL
              SELECT '5' UNION ALL
              SELECT '6' UNION ALL
              SELECT '7' UNION ALL
              SELECT '8' UNION ALL
              SELECT '9' UNION ALL
              SELECT '0') years 
              CROSS JOIN  
              (SELECT '-01' [month] UNION ALL
              SELECT '-02' UNION ALL
              SELECT '-03' UNION ALL
              SELECT '-04' UNION ALL
              SELECT '-05' UNION ALL
              SELECT '-06' UNION ALL
              SELECT '-07' UNION ALL
              SELECT '-08' UNION ALL
              SELECT '-09' UNION ALL
              SELECT '-10' UNION ALL
              SELECT '-11' UNION ALL
              SELECT '-12') [months]
              ORDER BY 1
              

              然后,将您的 Time1 和 Time2 日期点转换为“yyyy-mm”格式(将这些视为整块布料上的坐标切割点)。保留原来的 datetime 版本的点:

              SELECT
              Time1 = @Time1,
              [YYYY-MM of Time1] = CASE
              WHEN LEFT(MONTH(@Time1),1) <> '1' OR MONTH(@Time1) = '1'
                  THEN (CAST(YEAR(@Time1) AS VARCHAR) + '-' + '0' + CAST(MONTH(@Time1) AS VARCHAR))
                  ELSE (CAST(YEAR(@Time1) AS VARCHAR) + '-' + CAST(MONTH(@Time1) AS VARCHAR))
                  END,
              Time2 = @Time2,
              [YYYY-MM of Time2] = CASE
              WHEN LEFT(MONTH(@Time2),1) <> '1' OR MONTH(@Time2) = '1'
                  THEN (CAST(YEAR(@Time2) AS VARCHAR) + '-' + '0' + CAST(MONTH(@Time2) AS VARCHAR))
                  ELSE (CAST(YEAR(@Time2) AS VARCHAR) + '-' + CAST(MONTH(@Time2) AS VARCHAR))
                  END
              INTO #datepoints
              

              然后,选择'yyyy-mm'单位的序数距离,减去一个以转换为基数距离(即在确定的切割点从整块​​布料上剪下一块布并得到它的原始尺寸):

              SELECT 
              d.*,
              Months_Between = (SELECT (SUM(l.value) - 1) FROM #linear_months l
                          WHERE l.[Linear_YearMonths] BETWEEN d.[YYYY-MM of Time1] AND d.[YYYY-MM of Time2])
              FROM #datepoints d
              

              Raw Output: 我称之为“原始距离”,因为“yyyy-mm”基数距离的月份部分可能太多了;需要比较该月内的天周期分量,以查看上个月的值是否应该计算在内。具体而言,在本示例中,原始输出距离为“12”。但是这个错误,因为 12/14 早于 12/15,因此只有 11 个完整的月份已经过去了——距离第 12 个月只差一天。因此,我们必须引入月内日周期才能得出最终答案。在 之间插入 'month,day' 位置比较以确定最近的日期点月份是否名义上计数:

              SELECT 
              d.*,
              Months_Between = (SELECT (SUM(l.value) - 1) FROM AZ_VBP.[MY].[edg_Linear_YearMonths] l
                          WHERE l.[Linear_YearMonths] BETWEEN d.[YYYY-MM of Time1] AND d.[YYYY-MM of Time2])
                      + (CASE WHEN DAY(Time1) < DAY(Time2)
                              THEN -1
                              ELSE 0
                              END)
              FROM #datepoints d
              

              Final Output: '11' 的正确答案现在是我们的输出。所以,我希望这会有所帮助。谢谢!

              【讨论】:

                【解决方案11】:
                select CAST(DATEDIFF(MONTH, StartDate, EndDate) AS float) -
                  (DATEPART(dd,StartDate) - 1.0) / DATEDIFF(DAY, StartDate, DATEADD(MONTH, 1, StartDate)) +
                  (DATEPART(dd,EndDate)*1.0 ) / DATEDIFF(DAY, EndDate, DATEADD(MONTH, 1, EndDate))
                

                【讨论】:

                  【解决方案12】:

                  我意识到这是一篇旧帖子,但我创建了这个有趣的解决方案,我认为使用 CASE 语句很容易实现。

                  使用 DATEDIFF 估计差异,然后测试使用 DATEADD 前后的月份以找到最佳日期。这假设 1 月 31 日到 2 月 28 日是 1 个月(因为它是)。

                  DECLARE @First date = '2015-08-31'
                  DECLARE @Last date = '2016-02-28'
                  
                  SELECT
                      @First as [First],
                      @Last as [Last],
                      DateDiff(Month, @First, @Last) as [DateDiff Thinks],
                      CASE
                          WHEN DATEADD(Month, DATEDIFF(Month, @First, @Last) +1, @First) <= @Last Then DATEDIFF(Month, @First, @Last) +1
                          WHEN DATEADD(Month, DATEDIFF(Month, @First, @Last) , @First) <= @Last Then DATEDIFF(Month, @First, @Last) 
                          WHEN DATEADD(Month, DATEDIFF(Month, @First, @Last) -1, @First) <= @Last Then DATEDIFF(Month, @First, @Last) -1
                      END as [Actual Months Apart]
                  

                  【讨论】:

                  • "然后用 DATEADD 测试前后的几个月来找到最佳日期。",我不明白什么是找到“最佳日期”?
                  • 如果 startdate = 2020-01-31 和 enddae = 2020-01-30,虽然只有 1 天不同,但返回 -1
                  【解决方案13】:

                  简单易行,只需将此完整代码复制并粘贴到 MS SQL 并执行:

                  declare @StartDate date='2019-01-31'
                  declare @EndDate date='2019-02-28'
                  
                  
                  SELECT
                  
                  DATEDIFF(MONTH, @StartDate, @EndDate)+
                  
                  (
                  
                  case 
                  
                  when format(@StartDate,'yyyy-MM') != format(@EndDate,'yyyy-MM') AND DATEPART(DAY,@StartDate) > DATEPART(DAY,@EndDate) AND DATEPART(DAY,@EndDate) = DATEPART(DAY,EOMONTH(@EndDate)) then 0
                  
                  when format(@StartDate,'yyyy-MM') != format(@EndDate,'yyyy-MM') AND DATEPART(DAY,@StartDate) > DATEPART(DAY,@EndDate)  then -1 
                  
                  else 0 
                  
                  end
                  
                  ) 
                  
                  as NumberOfMonths
                  

                  【讨论】:

                    【解决方案14】:

                    如果结束日期尚未超过开始日期的月份,您只需扣除额外的月份。

                    DECLARE @StartDate AS DATE = '2019-07-17'
                    DECLARE @EndDate AS DATE = '2019-09-15'
                    
                    
                    DECLARE @MonthDiff AS INT = DATEDIFF(MONTH,@StartDate,@EndDate)
                    
                    SELECT @MonthDiff - 
                            CASE 
                                WHEN FORMAT(@StartDate,'dd') > FORMAT(@EndDate,'dd') THEN 1
                                ELSE 0
                            END
                    

                    【讨论】:

                      【解决方案15】:

                      您可以创建此函数来计算两个日期之间的绝对差。 正如我发现使用 DATEDIFF 内置系统功能一样,我们只会在几个月、几天和几年内获得差异。例如:假设有两个日期 18-Jan-2018 和 15-Jan-2019。因此,这些日期之间的差异将由 DATEDIFF 以 12 个月的形式给出,而实际上是 11 个月 28 天。所以使用下面给出的函数,我们可以找到两个日期之间的绝对差。

                      CREATE FUNCTION GetDurationInMonthAndDays(@First_Date DateTime,@Second_Date DateTime)
                      
                      RETURNS VARCHAR(500)
                      
                      AS
                      
                      BEGIN
                      
                          DECLARE @RESULT VARCHAR(500)=''
                      
                      
                      
                          DECLARE @MONTHS TABLE(MONTH_ID INT,MONTH_NAME VARCHAR(100),MONTH_DAYS INT)
                      
                          INSERT INTO @MONTHS
                      
                          SELECT 1,'Jan',31
                      
                          union SELECT 2,'Feb',28
                      
                          union SELECT 3,'Mar',31
                      
                          union SELECT 4,'Apr',30
                      
                          union SELECT 5,'May',31
                      
                          union SELECT 6,'Jun',30
                      
                          union SELECT 7,'Jul',31
                      
                          union SELECT 8,'Aug',31
                      
                          union SELECT 9,'Sep',30
                      
                          union SELECT 10,'Oct',31
                      
                          union SELECT 11,'Nov',30
                      
                          union SELECT 12,'Jan',31
                      
                      
                      
                          IF(@Second_Date>@First_Date)
                      
                          BEGIN
                      
                      
                      
                                  declare @month int=0
                      
                                  declare @days int=0
                      
                      
                      
                                  declare @first_year int
                      
                                  declare @second_year int
                      
                      
                      
                                  SELECT @first_year=Year(@First_Date)
                      
                                  SELECT @second_year=Year(@Second_Date)+1
                      
                      
                      
                                  declare @first_month int
                      
                                  declare @second_month int
                      
                      
                      
                                  SELECT @first_month=Month(@First_Date)
                      
                                  SELECT @second_month=Month(@Second_Date)    
                      
                      
                      
                                  if(@first_month=2)
                      
                                  begin
                      
                                         IF((@first_year%100<>0) AND (@first_year%4=0) OR (@first_year%400=0))
                      
                                           BEGIN
                      
                                            SELECT @days=29-day(@First_Date) 
                      
                                           END
                      
                                         else
                      
                                           begin
                      
                                            SELECT @days=28-day(@First_Date) 
                      
                                           end
                      
                                  end
                      
                                  else
                      
                                  begin
                      
                                    SELECT @days=(SELECT MONTH_DAYS FROM @MONTHS WHERE MONTH_ID=@first_month)-day(@First_Date) 
                      
                                  end
                      
                      
                      
                                  SELECT @first_month=@first_month+1
                      
                      
                      
                                  WHILE @first_year<@second_year
                      
                                  BEGIN
                      
                                     if(@first_month=13)
                      
                                     begin
                      
                                      set @first_month=1
                      
                                     end
                      
                                     WHILE @first_month<13
                      
                                     BEGIN
                      
                                         if(@first_year=Year(@Second_Date))
                      
                                         begin
                      
                                          if(@first_month=@second_month)
                      
                                          begin           
                      
                                           SELECT @days=@days+DAY(@Second_Date)
                      
                                           break;
                      
                                          end
                      
                                          else
                      
                                          begin
                      
                                           SELECT @month=@month+1
                      
                                          end
                      
                                         end
                      
                                         ELSE
                      
                                         BEGIN
                      
                                          SELECT @month=@month+1
                      
                                         END      
                      
                                      SET @first_month=@first_month+1
                      
                                     END
                      
                      
                      
                                  SET @first_year  = @first_year  + 1
                      
                                  END
                      
                      
                      
                                  select @month=@month+(@days/30)
                      
                                  select @days=@days%30
                      
                      
                      
                                  if(@days>0)
                      
                                  begin
                      
                                   SELECT @RESULT=CAST(@month AS VARCHAR)+' Month '+CAST(@days AS VARCHAR)+' Days '
                      
                                  end
                      
                                  else 
                      
                                  begin
                      
                                   SELECT @RESULT=CAST(@month AS VARCHAR)+' Month '
                      
                                  end
                      
                              END
                      
                      
                      
                              ELSE
                      
                              BEGIN
                      
                                 SELECT @RESULT='ERROR'
                      
                              END
                      
                      
                      
                      
                      
                          RETURN @RESULT 
                      
                      END
                      

                      【讨论】:

                        【解决方案16】:
                        SELECT dateadd(dd,number,DATEADD(yy, DATEDIFF(yy,0,getdate()), 0)) AS gun FROM master..spt_values
                        WHERE type = 'p'
                        AND year(dateadd(dd,number,DATEADD(yy, DATEDIFF(yy,0,getdate()), 0)))=year(DATEADD(yy, DATEDIFF(yy,0,getdate()), 0))
                        

                        【讨论】:

                        • 能补充一点小说明吗?
                        【解决方案17】:
                        CREATE FUNCTION ufFullMonthDif (@dStart DATE, @dEnd DATE)
                        RETURNS INT
                        AS
                        BEGIN
                            DECLARE @dif INT,
                                    @dEnd2 DATE
                            SET @dif = DATEDIFF(MONTH, @dStart, @dEnd)
                            SET @dEnd2 = DATEADD (MONTH, @dif, @dStart)
                            IF @dEnd2 > @dEnd
                                SET @dif = @dif - 1
                            RETURN @dif
                        END
                        GO
                        
                        SELECT dbo.ufFullMonthDif ('2009-04-30', '2009-05-01')
                        SELECT dbo.ufFullMonthDif ('2009-04-30', '2009-05-29')
                        SELECT dbo.ufFullMonthDif ('2009-04-30', '2009-05-30')
                        SELECT dbo.ufFullMonthDif ('2009-04-16', '2009-05-15')
                        SELECT dbo.ufFullMonthDif ('2009-04-16', '2009-05-16')
                        SELECT dbo.ufFullMonthDif ('2009-04-16', '2009-06-16')
                        SELECT dbo.ufFullMonthDif ('2019-01-31', '2019-02-28')
                        

                        【讨论】:

                          【解决方案18】:

                          对上述函数进行一些更改对我有用。

                          创建函数 [dbo].[FullMonthsSeparation] ( @DateA 日期时间, @DateB 日期时间 ) 返回整数 作为 开始 声明@Result INT

                          DECLARE @DateX DATETIME
                          DECLARE @DateY DATETIME
                          
                          IF(@DateA < @DateB)
                          BEGIN
                              SET @DateX = @DateA
                              SET @DateY = @DateB
                          END
                          ELSE
                          BEGIN
                              SET @DateX = @DateB
                              SET @DateY = @DateA
                          END
                          
                          SET @Result = (
                                          SELECT 
                                          CASE 
                                              WHEN DATEPART(DAY, @DateX) > DATEPART(DAY, @DateY)
                                              THEN DATEDIFF(MONTH, @DateX, @DateY) - iif(EOMONTH(@DateY) = @DateY, 0, 1)
                                              ELSE DATEDIFF(MONTH, @DateX, @DateY)
                                          END
                                          )
                          
                          RETURN @Result
                          

                          结束

                          【讨论】:

                            【解决方案19】:
                            Declare @FromDate datetime, @ToDate datetime, 
                                    @TotalMonth int ='2021-10-01', @TotalDay='2021-12-31' int, 
                                    @Month int = 0
                            
                               WHILE @ToDate > DATEADD(MONTH,@Month,@FromDate)
                                    BEGIN
                                        SET @Month = @Month +1
                                    END
                                SET @TotalMonth = @Month -1
                                SET @TotalDay = DATEDIFF(DAY, DATEADD(MONTH,@TotalMonth, @FromDate),@ToDate) +1
                                IF(@TotalDay = DAY(EOMONTH(@ToDate)))
                                    BEGIN
                                        SET @TotalMonth = @TotalMonth +1 
                                        SET @TotalDay =0    
                                    END
                            
                            Result @TotalMonth = 3, @TotalDay=0
                            

                            【讨论】:

                            • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
                            • 我在用那个
                            【解决方案20】:

                            如果您只使用 PostGres --

                            SELECT (DATE_PART('year', '2012-01-01'::date) - DATE_PART('year', '2011-10-02'::date)) * 12 +
                                          (DATE_PART('month', '2012-01-01'::date) - DATE_PART('month', '2011-10-02'::date));
                            

                            【讨论】:

                              【解决方案21】:
                              SELECT 12 * (YEAR(end_date) - YEAR(start_date)) +
                                  ((MONTH(end_date) - MONTH(start_date))) +
                                  SIGN(DAY(end_date) / DAY(start_date));
                              

                              这对我在 SQL SERVER 2000 上运行良好。

                              【讨论】:

                              • (MS-SQL 2014) 对于 2009-04-16 到 2009-05-15,返回 1 而不是 0。对于 2009-04-16 到 2009-05-16,返回 2 而不是1. 对于 2009-04-16 到 2009-06-16,这将返回 3 而不是 2。我很惊讶 SQL 2000 和 2014 之间存在如此大的差异
                              • 这不适用于所有场景。 2019-01-31 和 2019-03-01 之间的月份数。答案应该是 - 1。但是这个返回 2
                              【解决方案22】:

                              试试:

                              trunc(Months_Between(date2, date1))
                              

                              【讨论】:

                              • 什么 rdbms 使用 trunc(),而不是 sql-server?
                              【解决方案23】:

                              我在网上搜索了一下。 我发现的建议是在末尾添加 +1。

                              尝试这样做:

                              Declare @Start DateTime
                              Declare @End DateTime
                              
                              Set @Start = '11/1/07'
                              Set @End = '2/29/08'
                              
                              Select DateDiff(Month, @Start, @End + 1)
                              

                              【讨论】:

                              • 这对很多情况都不起作用,请检查他的第一个。
                              猜你喜欢
                              • 2019-06-07
                              • 2021-07-20
                              • 2018-04-13
                              • 1970-01-01
                              • 1970-01-01
                              • 1970-01-01
                              • 1970-01-01
                              • 1970-01-01
                              相关资源
                              最近更新 更多