以月份为单位的日期差异(带小数)

问题描述 投票:0回答:7

我的查询如下:

SELECT DATEDIFF(MONTH, convert(datetime,'01/01/2015',103),convert(datetime,'15/02/2015',103) )

我只需要1个月就可以得到结果。

我需要1.5个月才能得到结果。 (指1个月15天)。

我怎样才能得到输出?

sql-server
7个回答
9
投票

试试这个,它会计算出一个月“已使用”的准确百分比。它应该适用于所有日期。

DECLARE @from date = '2015-01-01'
DECLARE @to   date = '2015-02-15'

SELECT 
  datediff(month, @from, @to) - 1 +
  1-1.0*(day(@from)-1)/ day(dateadd(m, datediff(m,-1, @from), -1))
  + 1.0*(day(@to)-1)/ day(dateadd(m, datediff(m,-1, @to), -1))

结果:

1.5

请注意

from date = '2015-03-02'
to   date = '2015-04-02'

将在 1.001075268817 中给出比 1 稍高的结果,因为在“from”之前经过的三月份的百分比比“to”之前经过的四月的百分比要小


5
投票

用这个代替:

SELECT DATEDIFF(d, convert(datetime,'01/01/2015',103),
                   convert(datetime,'15/02/2015',103) ) / 30.0
使用

d
代替
month
来获取天数。然后除以 30 即可得到所需的结果。

注意,您必须使用

30.0
而不是
30
以避免整数除法。


2
投票

这将是更正确的解决方案:

SELECT  DATEDIFF(m, CONVERT(DATETIME, '01/01/2015', 103),
                 CONVERT(DATETIME, '15/02/2015', 103)) + 
        DATEPART(DAY, CONVERT(DATETIME, '15/02/2015', 103)) / 30.0

显示差异:

SELECT  DATEDIFF(d, CONVERT(DATETIME, '01/01/2015', 103),
                 CONVERT(DATETIME, '15/03/2015', 103)) / 30.0

2.433333

SELECT  DATEDIFF(m, CONVERT(DATETIME, '01/01/2015', 103),
                 CONVERT(DATETIME, '15/03/2015', 103)) + 
        DATEPART(DAY, CONVERT(DATETIME, '15/03/2015', 103)) / 30.0

2.500000

更准确地说,您可以不除以 30.0,而可以除以上个月的天数:

SELECT  DATEDIFF(m, CONVERT(DATETIME, '01/01/2015', 103),
                 CONVERT(DATETIME, '15/02/2015', 103)) + 
        (DATEPART(DAY, CONVERT(DATETIME, '15/02/2015', 103))
        / (1.0*DATEDIFF(day, CONVERT(DATETIME, '15/02/2015', 103), dateadd(month, 1, CONVERT(DATETIME, '15/02/2015', 103)))))


1.53571428571428

编辑:

如果 StartDate 不是从第一天开始,那么这个版本将无法工作!然后坚持其他用户之一的回答。


2
投票

改进之前的答案

要计算月数,可以将其分为三部分。从月初到月末的部分月份、整个月份以及最后一个月的部分内容。

DECLARE @STARTDATE DATETIME = CONVERT(DATETIME, '22/01/2015', 103)
DECLARE @ENDDATE DATETIME = CONVERT(DATETIME, '15/03/2015', 103)

SELECT  -- Whole months
        DATEDIFF(m, @STARTDATE, @ENDDATE) - 1
        +
        -- Part of the month at beginning  of the period
        (1.0*((DAY(EOMONTH(@STARTDATE))) - DATEPART(DAY, @STARTDATE) + 1)
        / DAY(EOMONTH(@STARTDATE))) -- Number of days in first month
        + 
        -- Part of the month at the end of the period
        (1.0*DATEPART(DAY, @ENDDATE)
        / DAY(EOMONTH(@ENDDATE))) -- Number of days in last month

一个月的天数可以通过两种方式计算:

 DAY(EOMONTH(@DATE))) 

 (DATEDIFF(day, @DATE, dateadd(month, 1, @DATE)))

0
投票

试试这个:

SELECT DATEDIFF(d, convert(datetime,'01/01/2015',103),
   convert(datetime,'15/02/2015',103) ) / 30.0

即,您需要从 DATEDIFF 获取天数而不是月份,然后将其除以 30 以获得所需的输出。


0
投票

尝试以下查询来获取月份和日期:

DECLARE @from date = '2015-01-01'
DECLARE @to   date = '2015-03-2'

DECLARE @castdate date= CAST(CAST(datePart(year,@to) AS nvarchar(100)) + '-' + CAST(datePart(month,@to) AS nvarchar(100)) + '-' + CAST(datePart(day,@from) AS nvarchar(100)) AS DATE);

DECLARE @TotalDays int= datediff(day,@from,@to);
DECLARE @MonthDays int= datediff(day,@from,@castdate);
print cast((datediff(month,@from,@castdate)) as nvarchar(100))+'.'+ convert(nvarchar(150),(@TotalDays-@MonthDays))

0
投票

我想分享我复杂的实现函数,用于计算具有浮点输出的日期之间的持续时间(以月为单位)。也许,它可以帮助某人。 !注意它是为 mariadb 10.3 编写的,因此 TIMESTAMPDIFF 的工作方式与 mysql-server 中的 datediff 不同

DELIMITER //
DROP FUNCTION IF EXISTS leap_year;
DROP FUNCTION IF EXISTS date_diff_in_months;
CREATE FUNCTION leap_year(date DATE) RETURNS BOOLEAN
BEGIN
    RETURN IF(YEAR(date) % 4 = 0, TRUE, FALSE);
END;

CREATE FUNCTION date_diff_in_months(startDate DATE, endDate DATE) RETURNS FLOAT
BEGIN
    DECLARE floatVal FLOAT;
    DECLARE remainder FLOAT;
    SET @sign = 1;

    IF (startDate > endDate) THEN
        SET @temp = startDate;
        SET startDate = endDate;
        SET endDate = @temp;
        SET @sign = -1;
    END IF;

    SET floatVal =  ROUND(
            TIMESTAMPDIFF(MONTH, DATE_FORMAT(startDate, '%Y-%m-01'), DATE_FORMAT(endDate, '%Y-%m-01')) +
            (DAY(endDate) / DAY(LAST_DAY(endDate))) -
            (DAY(startDate) / DAY(LAST_DAY(startDate))) +
            IF (MONTH(startDate) != MONTH(endDate) and MONTH(startDate) = 2, IF (leap_year(startDate), 0.02, 0.03) , 0),
            2
                    );


    SET remainder = ROUND(floatVal % 1, 2);

    IF (remainder = 0) THEN
        RETURN floatVal * @sign;
    END IF;

    /* error 0.02 rounding */
    IF (remainder >= 0.5 and (1 - remainder) <= 0.02) THEN
        SET floatVal = floatVal + (1 - remainder);
    ELSEIF (remainder < 0.5 and remainder <= 0.02) THEN
        SET floatVal = floatVal - remainder;
    END IF;
    RETURN floatVal * @sign;
END;
//
DELIMITER ;

SELECT
    date_diff_in_months('2024-02-15', '2024-03-15'),#1
    date_diff_in_months('2025-02-15', '2025-03-15'),#1
    date_diff_in_months('2024-02-15', '2024-04-15'),#2
    date_diff_in_months('2025-02-15', '2025-04-15'),#2
    date_diff_in_months('2024-01-15', '2024-04-15'),#3
    date_diff_in_months('2025-01-15', '2025-04-15'),#3
    date_diff_in_months('2025-01-15', '2025-04-20'),#3.18
    date_diff_in_months('2024-01-15', '2025-01-15'),#12
    date_diff_in_months('2024-01-15', '2025-04-20'),#15.18
    date_diff_in_months('2024-04-15', '2025-01-15'),#9
    date_diff_in_months('2024-04-15', '2025-01-20'),#9.15
    date_diff_in_months('2024-04-15', '2025-01-25'),#9.31
    date_diff_in_months('2024-06-30', '2024-07-30'),#0.97
    date_diff_in_months('2024-06-30', '2024-07-31'),#1
    date_diff_in_months('2024-06-30', '2024-08-01'),#1.03
    date_diff_in_months('2024-08-01', '2024-06-30')#-1.03
;
© www.soinside.com 2019 - 2024. All rights reserved.