1. 程式人生 > >sqlserver中返回兩個日期間相差幾年零幾月零幾天,DATEDIFF通常不準確

sqlserver中返回兩個日期間相差幾年零幾月零幾天,DATEDIFF通常不準確

--實際差12月+1天
select DATEDIFF(M,'2013-08-31','2014-09-01') as [13]
,DATEDIFF(D,'2013-08-31','2014-09-01') AS [366]
,DATEDIFF(D,'2013-08-31','2014-09-01')/30 AS [12]
,DATEDIFF(D,'2013-08-31','2014-09-01')%30 AS [6]


--實際差12月+30天
select DATEDIFF(M,'2013-08-01','2014-08-31') AS [12]
,DATEDIFF(D,'2013-08-01','2014-08-31') AS [395]
,DATEDIFF(D,'2013-08-01','2014-08-31')/30 AS [13]
,DATEDIFF(D,'2013-08-01','2014-08-31')%30 AS [5]


/*

 返回兩個日期間相差幾年零幾月零幾天
 @interval IN ('Y','YEAR','M','MONTH','D','DAY')
 
 不知道為什麼,程式碼一樣,儲存過程正確,函式的不正確!求解!!!!

*/
CREATE FUNCTION DBO.getDateDiff(@Interval varchar(10),@startDate DATETIME,@endDate DATETIME)
RETURNS VARCHAR
AS 
BEGIN
 DECLARE @RETURN VARCHAR(10)
 DECLARE @startDatetime DATETIME
 DECLARE @endDatetime DATETIME
 SET @startDatetime = @startDate
 SET @endDatetime = @endDate

 IF @Interval NOT IN('Y','YEAR','M','MONTH','D','DAY') OR DATEDIFF(D,@startDatetime,@endDatetime)<0
	RETURN -1

 --返回相差年份	
 IF @interval IN ('Y','YEAR')
	SET @RETURN = DATEDIFF(D,@startDatetime,@endDatetime)/365
 	 
 --返回相差年份後相差的月份	
 IF @Interval IN ('M','MONTH')
 BEGIN
	SET @startDatetime = DATEADD(YEAR,DATEDIFF(D,@startDatetime,@endDatetime)/365,@startDatetime)
	IF DAY(@startDatetime) <= DAY(@endDatetime)
		SET @RETURN = DATEDIFF(M,@startDatetime,@endDatetime)
	ELSE
		SET @RETURN = DATEDIFF(M,@startDatetime,DATEADD(M,-1,@endDatetime))
 END

 --返回相差月份後相差的天數
 IF @Interval IN ('D','DAY')
 BEGIN
	SET @startDatetime = DATEADD(YEAR,DATEDIFF(D,@startDatetime,@endDatetime)/365,@startDatetime)
	IF DAY(@startDatetime) <= DAY(@endDatetime)
		SET @startDatetime = DATEADD(M,DATEDIFF(M,@startDatetime,@endDatetime),@startDatetime)
	ELSE
		SET @startDatetime = DATEADD(M,DATEDIFF(M,@startDatetime,DATEADD(M,-1,@endDatetime)),@startDatetime)
	SET @RETURN = DATEDIFF(D,@startDatetime,@endDatetime)
 END

return @RETURN
END

/*
SELECT DBO.getDateDiff('Y','2013-08-23','2015-11-11')
SELECT DBO.getDateDiff('M','2013-08-23','2015-11-11')
SELECT DBO.getDateDiff('D','2013-08-23','2015-11-11')

結果:
2
2
1	

*/


CREATE PROCEDURE DBO.getDateDiffKK(@Interval varchar(10),@startDate DATETIME,@endDate DATETIME)
AS 
BEGIN
 DECLARE @RETURN VARCHAR(10)
 DECLARE @startDatetime DATETIME
 DECLARE @endDatetime DATETIME
 SET @startDatetime = @startDate
 SET @endDatetime = @endDate

 IF @Interval NOT IN('Y','YEAR','M','MONTH','D','DAY') OR DATEDIFF(D,@startDatetime,@endDatetime)<0
	RETURN -1

 --返回相差年份	
 IF @interval IN ('Y','YEAR')
	SET @RETURN = DATEDIFF(D,@startDatetime,@endDatetime)/365
 	 
 --返回相差年份後相差的月份	
 IF @Interval IN ('M','MONTH')
 BEGIN
	SET @startDatetime = DATEADD(YEAR,DATEDIFF(D,@startDatetime,@endDatetime)/365,@startDatetime)
	IF DAY(@startDatetime) <= DAY(@endDatetime)
		SET @RETURN = DATEDIFF(M,@startDatetime,@endDatetime)
	ELSE
		SET @RETURN = DATEDIFF(M,@startDatetime,DATEADD(M,-1,@endDatetime))
 END

 --返回相差月份後相差的天數
 IF @Interval IN ('D','DAY')
 BEGIN
	SET @startDatetime = DATEADD(YEAR,DATEDIFF(D,@startDatetime,@endDatetime)/365,@startDatetime)
	IF DAY(@startDatetime) <= DAY(@endDatetime)
		SET @startDatetime = DATEADD(M,DATEDIFF(M,@startDatetime,@endDatetime),@startDatetime)
	ELSE
		SET @startDatetime = DATEADD(M,DATEDIFF(M,@startDatetime,DATEADD(M,-1,@endDatetime)),@startDatetime)
	SET @RETURN = DATEDIFF(D,@startDatetime,@endDatetime)
 END

SELECT @RETURN
END

/*

EXEC getDateDiffKK 'Y','2013-08-23','2015-11-11' 
EXEC getDateDiffKK 'M','2013-08-23','2015-11-11' 
EXEC getDateDiffKK 'D','2013-08-23','2015-11-11' 
結果:
2
2
19

*/


--選擇時計算結果:

DECLARE @QSRQ VARCHAR(10)
DECLARE @JSRQ VARCHAR(10)
SET @QSRQ ='2013-08-23'
SET @JSRQ ='2015-11-11'
SELECT
	CASE WHEN DAY(@QSRQ) <= DAY(@JSRQ) THEN DATEDIFF(M,@QSRQ,@JSRQ)
	ELSE DATEDIFF(M,@QSRQ,DATEADD(M,-1,@JSRQ)) end  AS 月份數
,CASE WHEN DAY(@QSRQ) <= DAY(@JSRQ) THEN DATEDIFF(D,DATEADD(M,DATEDIFF(M,@QSRQ,@JSRQ),@QSRQ),@JSRQ)
	ELSE DATEDIFF(D,DATEADD(M,DATEDIFF(M,@QSRQ,DATEADD(M,-1,@JSRQ)),@QSRQ),@JSRQ) end  AS 天數
/*
結果:
月份數	天數
26		19

日期差26個月零19天
*/

--錯誤:
select DATEDIFF(M,@QSRQ,@JSRQ) --26
select DATEDIFF(D,@QSRQ,@JSRQ) --810

2016-08-30 補充 -------------------------------

ALTER FUNCTION DBO.getDateDiff(@startDate DATETIME,@endDate DATETIME)  
RETURNS VARCHAR(10) --長度設定
AS   
BEGIN  
	RETURN DATEDIFF(D,@startDate,@endDate)
END
GO

ALTER FUNCTION DBO.getDateDiff(@startDate DATETIME,@endDate DATETIME)  
RETURNS INT  --返回整形
AS   
BEGIN  
	RETURN DATEDIFF(D,@startDate,@endDate)
END
GO


--儲存過程:正確
ALTER PROCEDURE DBO.getDateDiffKK(@startDate DATETIME,@endDate DATETIME)  
AS   
BEGIN  
	SELECT DATEDIFF(D,@startDate,@endDate)  
END  
GO

--執行結果:
SELECT DBO.getDateDiff('2013-08-23','2015-11-11') 
GO
EXEC DBO.getDateDiffKK '2013-08-23','2015-11-11'
GO