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。
日期部分边界
以下语句具有相同的 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 类型。在将 DATEDIFF 用于 DATEADD 时,应避免隐式转换字符串文字。有关详细信息,请参阅 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