DATEDIFF (Transact-SQL)

傳回跨越指定之 startdate 與 enddate 之指定 datepart 界限的計數 (帶正負號的整數)。

如需所有 Transact-SQL 日期和時間資料類型與函數的概觀,請參閱<日期和時間資料類型與函數 (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 子句中。在 SQL Server 2008 中,DATEDIFF 會隱含地將字串常值轉換為 datetime2 類型。搭配 DATEADD 使用 DATEDIFF 時,請避免字串常值的隱含轉換。如需詳細資訊,請參閱<DATEADD (Transact-SQL)>。

範例

下列範例會使用不同的運算式類型,當做 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 AdventureWorks;
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 的引數。

[!附註]

SYSDATETIME、SYSUTCDATETIME 和 SYSDATETIMEOFFSET 不得屬於算術運算式的一部分。

USE AdventureWorks;
GO
SELECT DATEDIFF(day, '2007-05-07 09:53:01.0376635', GETDATE()+ 1) 
    AS NumberOfDays
FROM Sales.SalesOrderHeader;
GO
USE AdventureWorks;
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 AdventureWorks;
GO
SELECT c.FirstName, c.LastName
    ,DATEDIFF(day,ROW_NUMBER() OVER (ORDER BY 
        a.PostalCode),SYSDATETIME()) AS 'Row Number'
FROM Sales.SalesPerson s 
    INNER JOIN Person.Contact c 
        ON s.SalesPersonID = c.ContactID
    INNER JOIN Person.Address a 
        ON a.AddressID = c.ContactID
WHERE TerritoryID IS NOT NULL 
    AND SalesYTD <> 0;

H. 指定 startdate 的彙總視窗函數

下列範例會使用彙總視窗函數,當做 startdate 的引數。

USE AdventureWorks;
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