Sql 需要计算截止日期的年、月和日
我有一张叫dates的桌子Sql 需要计算截止日期的年、月和日,sql,sql-server,sql-server-2008,date,Sql,Sql Server,Sql Server 2008,Date,我有一张叫dates的桌子 Opendate | Closedate ------------+--------------- 2015-07-09 | 2016-08-10 我期待的结果是 opendate | closedate | diff ------------+---------------+---------------------- 2015-07-09 | 2016-08-10 | 1year 1month 1d
Opendate | Closedate
------------+---------------
2015-07-09 | 2016-08-10
我期待的结果是
opendate | closedate | diff
------------+---------------+----------------------
2015-07-09 | 2016-08-10 | 1year 1month 1day
2015-07-09 | 2016-03-01 | 8 months 20 days
2015-07-09 | 2015-07-11 | 2 days
opendate | closedate | years | months | days
------------+---------------+-------+--------+---------
2015-07-09 | 2016-08-10 | 1 | 13 | 397
但当我运行此查询时:
SELECT opendate,
closedate,
Datediff(year, opendate, closedate) AS years,
Datediff(month, opendate, closedate) AS months,
Datediff(day, opendate, closedate) AS days
FROM dates
它给了我一个输出,比如
opendate | closedate | diff
------------+---------------+----------------------
2015-07-09 | 2016-08-10 | 1year 1month 1day
2015-07-09 | 2016-03-01 | 8 months 20 days
2015-07-09 | 2015-07-11 | 2 days
opendate | closedate | years | months | days
------------+---------------+-------+--------+---------
2015-07-09 | 2016-08-10 | 1 | 13 | 397
我们如何计算1年1月1日
SELECT opendate,
closedate,
( ( Datediff(year, opendate, closedate) + 'years' )+
(( Datediff(month, opendate, closedate) -
12 * Datediff(year, opendate, closedate)) + 'months') +
( Datediff(day, opendate, closedate) -
( Datediff(year, opendate, closedate) * 365 -
(Datediff(month, opendate, closedate) * 12) )) + 'days'
FROM dates
逻辑是将年份串联起来,然后减去一年中的月数。同样扣除天数您可以使用堆叠CTE逐个查找下一年、下一个月和下一个日期 解释 下面的查询首先找出opendate和closedate的
DATEDIFF
年份,并检查结果日期是否大于closedate。如果是,实际年份差异为Y-1的DATEDIFF
。使用此新日期,使用相同的逻辑获取月份的DATEDIFF
,然后以天为单位获取差值
查询
WITH D(Opendate,Closedate)AS
(
SELECT CAST('2015-07-09' AS DATE),CAST('2016-08-10' AS DATE)
UNION ALL
SELECT CAST('2015-07-09' AS DATE),CAST('2016-03-01' AS DATE)
UNION ALL
SELECT CAST('2015-07-09' AS DATE),CAST('2015-07-11' AS DATE)
),Y AS
(
SELECT Opendate,Closedate,
CASE
WHEN DATEADD(YEAR,DATEDIFF(YEAR,Opendate,Closedate),Opendate) > Closedate
THEN DATEDIFF(YEAR,Opendate,Closedate) - 1
ELSE DATEDIFF(YEAR,Opendate,Closedate)
END Years
FROM D
), YDate as
(
SELECT Opendate,Closedate,Years,DATEADD(YEAR,Years,Opendate) as Newopendate
FROM Y
),M AS
(
SELECT Opendate,Closedate,Years,Newopendate,
CASE WHEN DATEADD(MONTH,DATEDIFF(MONTH,Newopendate,Closedate),Newopendate) > Closedate
THEN DATEDIFF(MONTH,Newopendate,Closedate) - 1
ELSE DATEDIFF(MONTH,Newopendate,Closedate)
END Months
FROM YDate
)
SELECT Opendate,Closedate,Years,Months,DATEDIFF(Day,DATEADD(MONTH,Months,Newopendate),Closedate) as days
FROM M
结果
Opendate Closedate Years Months days
09-07-2015 00:00 10-08-2016 00:00 1 1 1
09-07-2015 00:00 01-03-2016 00:00 0 7 21
09-07-2015 00:00 11-07-2015 00:00 0 0 2
创建一个函数,如下所示
CREATE FUNCTION dbo.GetYearMonthDays
(
@FromDate DATETIME
)
RETURNS NVARCHAR(100)
AS
BEGIN
DECLARE @date datetime, @tmpdate datetime, @years int, @months int, @days int
SELECT @date =@FromDate
SELECT @tmpdate = @date
SELECT @years = DATEDIFF(yy, @tmpdate, GETDATE()) - CASE WHEN (MONTH(@date) > MONTH(GETDATE())) OR (MONTH(@date) = MONTH(GETDATE()) AND DAY(@date) > DAY(GETDATE())) THEN 1 ELSE 0 END
SELECT @tmpdate = DATEADD(yy, @years, @tmpdate)
SELECT @months = DATEDIFF(m, @tmpdate, GETDATE()) - CASE WHEN DAY(@date) > DAY(GETDATE()) THEN 1 ELSE 0 END
SELECT @tmpdate = DATEADD(m, @months, @tmpdate)
SELECT @days = DATEDIFF(d, @tmpdate, GETDATE())
RETURN CONVERT(varchar(10), @years) +' Years ' + CONVERT(varchar(10), @months) + ' Month ' + CONVERT(varchar(10), @days) + ' Days'
END
GO
使用方法如下
SELECT opendate,
closedate,dbo.GetYearMonthDays(closedate)
FROM dates
这会给你你想要的。当
关闭日期为2016-03-01
@Prdp时结果应该是什么?当关闭日期2015-07-11
时结果应该是2天mind@prdp一点也不,实际上是好消息245,将varchar值“years”转换为数据类型int时,级别16,状态1,第11行转换失败。