SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
/*
名称:[dbo].[f_getDateIntervalMulti]
功能:根据2个日期,计算年月日的差值
测试用例:
select [dbo].[f_getDateIntervalMulti] ('2022-01-01','2022-06-30','Y',2)
*/
CREATE FUNCTION [dbo].[f_getDateIntervalMulti] (@d1 AS DATETIME,--开始日期
@d2 AS DATETIME,--结束日期
@type VARCHAR(10),--年月日Y,M,D
@flag INT--保留小数位0,2,4
)
RETURNS NVARCHAR(100)
AS
BEGIN
--函数默认@d1 <= @d2,如果@d1 > @d2,则交换
IF @d1 > @d2
BEGIN
DECLARE @d3 AS DATETIME
SET @d3 = @d1
SET @d1 = @d2
SET @d2 = @d3
END
DECLARE @yy AS INT,
@mm AS INT,
@dd AS INT
--先直接判断月数,每年的12个月是固定的
SET @mm = Datediff(MONTH, @d1, @d2)
--当@d1的日大于@d2+1的日(不到1个月),则月份-1
IF Day(@d1) > Day(@d2) + 1
BEGIN
SET @mm = @mm - 1
END
--将@d1日期直接增加已获得的月数,以便后面直接判断天数
SET @d1 = Dateadd(MONTH, @mm, @d1)
--根据@mm,获取年数
SET @yy = @mm / 12
--根据@mm,将@mm取余数,获取月数
SET @mm = @mm % 12
--获取@dd的天数,此时的@d1已经是接近@d2日期了
SET @dd = Datediff(DAY, @d1, @d2) + 1
--将@d1日期增加1个月,并减去1天,判断是否与@d2相同(满月判断)
SET @d1 = Dateadd(MONTH, 1, @d1)
SET @d1 = Dateadd(DAY, -1, @d1)
--如果相同,则表示天数进位(满月),日期进位,月份+1
IF @d1 = @d2
BEGIN
SET @mm = @mm + 1
SET @dd = 0
END
--最后也是判断月数是否有进位。判断@mm是否为12(逢12进1),如果是则年份+1,即@yy+1,然后@mm设为0
IF @mm = 12
BEGIN
SET @yy = @yy + 1
SET @mm = 0
END
DECLARE @num DECIMAL(18, 8)
DECLARE @str AS NVARCHAR(100)
SET @str=''
IF @type = 'Y'
BEGIN
SET @num=@yy + @mm / 12.0 + @dd / 365.0
END
IF @type = 'M'
BEGIN
SET @num=@yy * 12 + @mm + @dd / 30.0
END
IF @type = 'D'
BEGIN
SET @num=@yy * 365 + @mm * 30 + @dd
END
IF @flag = 0
BEGIN
SET @str=CONVERT(VARCHAR(100), CONVERT(DECIMAL(18, 0), @num))
END
ELSE IF @flag = 4
BEGIN
SET @str=CONVERT(VARCHAR(100), CONVERT(DECIMAL(18, 4), @num))
END
ELSE
BEGIN
SET @str=CONVERT(VARCHAR(100), CONVERT(DECIMAL(18, 2), @num))
END
RETURN @str
END