DATEDIFF (Transact-SQL)
傳回跨越指定 startdate 與 enddate 之指定 datepart 界限的計數 (帶正負號的整數)。
如需所有 Transact-SQL 日期和時間資料類型與函數的概觀,請參閱<日期和時間資料類型與函數 (Transact-SQL)>。
語法
DATEDIFF ( datepart , startdate , enddate )
引數
datepart
這是指定所跨越之界限類型的 startdate 和 enddate 部分。下表列出所有有效的 datepart 引數。使用者自訂變數對等項目無效。datepart
縮寫
year
yy, yyyy
quarter
qq, q
month
mm, m
dayofyear
dy, y
day
dd, d
week
wk, ww
hour
hh
minute
mi, n
second
ss, s
millisecond
ms
microsecond
mcs
nanosecond
ns
startdate
這是可解析成 time、date、smalldatetime、datetime、datetime2 或 datetimeoffset 值的運算式。date 可以是運算式、資料行運算式、使用者自訂變數或字串常值。從 enddate 中扣除 startdate。若要避免模糊不清,請使用四位數年份。如需兩位數年份的詳細資訊,請參閱<設定 two digit year cutoff 伺服器組態選項>。
enddate
請參閱<startdate>。
傳回類型
int
傳回值
每個 datepart 及其縮寫都會傳回相同的值。
如果傳回值超出 int 的範圍 (-2,147,483,648 到 +2,147,483,647),就會傳回錯誤。若為 millisecond,startdate 與 enddate 之間的最大差異是 24 天、20 小時、31 分鐘和 23.647 秒。若為 second,最大差異是 68 年。
如果 startdate 和 enddate 都只被指派時間值,而且 datepart 不是時間 datepart,就會傳回 0。
startdate 或 endate 的時區位移元件不會用於計算傳回值。
由於 smalldatetime 的精確度只有到分鐘,因此當 smalldatetime 值用於 startdate 或 enddate 時,秒鐘和毫秒就一律會在傳回值中設定為 0。
若您只將時間值指派給日期資料類型的變數,便會將缺少之日期部分的值設定為預設值:1900-01-01。若您只將日期值指派給時間或日期資料類型的變數,便會將缺少之時間部分的值設定為預設值:00:00:00。如果 startdate 或 enddate 其中之一只有時間部分,而且另一個項目只有日期部分,則遺漏的時間和日期部分都會設定為預設值。
如果 startdate 和 enddate 具有不同的日期資料類型,而且其中一個項目的時間部分或小數秒數有效位數超過另一個項目,則另一個項目的遺漏部分就會設定為 0。
datepart 界限
下列陳述式具有相同的 startdate 和相同的 endate。這些日期都很接近而且時間差距為 .0000001 秒。每個陳述式中 startdate 與 endate 之間的差異會跨越其 datepart 的日曆或時間界限。每個陳述式都傳回 1。若在此範例中使用不同的年份,且 startdate 及 endate 都在相同的日曆週內,week 的傳回值為 0。
SELECT DATEDIFF(year, '2005-12-31 23:59:59.9999999'
, '2006-01-01 00:00:00.0000000');
SELECT DATEDIFF(quarter, '2005-12-31 23:59:59.9999999'
, '2006-01-01 00:00:00.0000000');
SELECT DATEDIFF(month, '2005-12-31 23:59:59.9999999'
, '2006-01-01 00:00:00.0000000');
SELECT DATEDIFF(dayofyear, '2005-12-31 23:59:59.9999999'
, '2006-01-01 00:00:00.0000000');
SELECT DATEDIFF(day, '2005-12-31 23:59:59.9999999'
, '2006-01-01 00:00:00.0000000');
SELECT DATEDIFF(week, '2005-12-31 23:59:59.9999999'
, '2006-01-01 00:00:00.0000000');
SELECT DATEDIFF(hour, '2005-12-31 23:59:59.9999999'
, '2006-01-01 00:00:00.0000000');
SELECT DATEDIFF(minute, '2005-12-31 23:59:59.9999999'
, '2006-01-01 00:00:00.0000000');
SELECT DATEDIFF(second, '2005-12-31 23:59:59.9999999'
, '2006-01-01 00:00:00.0000000');
SELECT DATEDIFF(millisecond, '2005-12-31 23:59:59.9999999'
, '2006-01-01 00:00:00.0000000');
備註
DATEDIFF 可用於選取清單、WHERE、HAVING、GROUP BY 和 ORDER BY 子句中。
DATEDIFF 會隱含地將字串常值轉換為 datetime2 類型。這表示,將日期當做字串傳遞時,DATEDIFF 不支援 YDM 格式。您必須明確地將字串轉換為 datetime 或 smalldatetime 類型,才能使用 YDM 格式。
指定 SET DATEFIRST 對 DATEDIFF 沒有任何作用。DATEDIFF 一定會使用星期天當做一週的第一天,以確保此函數具決定性。
範例
下列範例會使用不同的運算式類型,當做 startdate 和 enddate 參數的引數。
A. 指定 startdate 和 enddate 的資料行
下列範例會計算資料表中兩個資料行之間的日期已跨越的天數界限。
CREATE TABLE dbo.Duration
(
startDate datetime2
,endDate datetime2
);
INSERT INTO dbo.Duration(startDate,endDate)
VALUES('2007-05-06 12:10:09','2007-05-07 12:10:09');
SELECT DATEDIFF(day,startDate,endDate) AS 'Duration'
FROM dbo.Duration;
-- Returns: 1
B. 指定 startdate 和 enddate 的使用者自訂變數
下列範例會使用使用者自訂變數,當做 startdate 和 enddate 的引數。
DECLARE @startdate datetime2 = '2007-05-05 12:10:09.3312722';
DECLARE @enddate datetime2 = '2007-05-04 12:10:09.3312722';
SELECT DATEDIFF(day, @startdate, @enddate);
C. 指定 startdate 和 enddate 的純量系統函數
下列範例會使用純量系統函數,當做 startdate 和 enddate 的引數。
SELECT DATEDIFF(millisecond, GETDATE(), SYSDATETIME());
D. 指定 startdate 和 enddate 的純量子查詢和純量函數
下列範例會使用純量子查詢和純量函數,當做 startdate 和 enddate 的引數。
USE AdventureWorks2012;
GO
SELECT DATEDIFF(day,(SELECT MIN(OrderDate) FROM Sales.SalesOrderHeader),
(SELECT MAX(OrderDate) FROM Sales.SalesOrderHeader));
E. 指定 startdate 和 enddate 的常數
下列範例會使用字元常數,當做 startdate 和 enddate 的引數。
SELECT DATEDIFF(day, '2007-05-07 09:53:01.0376635'
, '2007-05-08 09:53:01.0376635');
F. 指定 enddate 的數值運算式和純量系統函數
下列範例會使用數值運算式 (GETDATE ()+ 1) 和純量系統函數 GETDATE 與 SYSDATETIME,當做 enddate 的引數。
USE AdventureWorks2012;
GO
SELECT DATEDIFF(day, '2007-05-07 09:53:01.0376635', GETDATE()+ 1)
AS NumberOfDays
FROM Sales.SalesOrderHeader;
GO
USE AdventureWorks2012;
GO
SELECT DATEDIFF(day, '2007-05-07 09:53:01.0376635', DATEADD(day,1,SYSDATETIME())) AS NumberOfDays
FROM Sales.SalesOrderHeader;
GO
G. 指定 startdate 的排名函數
下列範例會使用排名函數,當做 startdate 的引數。
USE AdventureWorks2012;
GO
SELECT p.FirstName, p.LastName
,DATEDIFF(day,ROW_NUMBER() OVER (ORDER BY
a.PostalCode),SYSDATETIME()) AS 'Row Number'
FROM Sales.SalesPerson s
INNER JOIN Person.Person p
ON s.BusinessEntityID = p.BusinessEntityID
INNER JOIN Person.Address a
ON a.AddressID = p.BusinessEntityID
WHERE TerritoryID IS NOT NULL
AND SalesYTD <> 0;
H. 指定 startdate 的彙總視窗函數
下列範例會使用彙總視窗函數,當做 startdate 的引數。
USE AdventureWorks2012;
GO
SELECT soh.SalesOrderID, sod.ProductID, sod.OrderQty,soh.OrderDate
,DATEDIFF(day,MIN(soh.OrderDate)
OVER(PARTITION BY soh.SalesOrderID),SYSDATETIME() ) AS 'Total'
FROM Sales.SalesOrderDetail sod
INNER JOIN Sales.SalesOrderHeader soh
ON sod.SalesOrderID = soh.SalesOrderID
WHERE soh.SalesOrderID IN(43659,58918);
GO