sql,dateadd,datediff
本文转载自MSDN,为了方便访问,谢谢!
DATEADD (Transact-SQL)
http://msdn.microsoft.com/zh-cn/library/ms186819.aspx
将指定 number 时间间隔(有符号整数)与指定 date 的指定 datepart 相加后,返回该 date。
有关所有 Transact-SQL 日期和时间数据类型及函数的概述,请参阅日期和时间数据类型及函数 (Transact-SQL)。有关日期和时间数据类型及函数共有的信息和示例,请参阅使用日期和时间数据。
Transact-SQL 语法约定
语法| DATEADD (datepart , number, date ) |
是与 integer number 相加的 date 部分。下表列出了所有有效的 datepart 参数。用户定义的变量等效项是无效的。
| year | yy, yyyy |
| quarter | qq, q |
| month | mm, m |
| dayofyear | dy, y |
| day | dd, d |
| week | wk, ww |
| weekday | dw, w |
| hour | hh |
| minute | mi, n |
| second | ss, s |
| millisecond | ms |
| microsecond | mcs |
| nanosecond | ns |
是一个表达式,可以解析为与 date 的 datepart 相加的 int。用户定义的变量是有效的。
如果您指定一个带小数的值,则将小数截去且不进行舍入。
是一个表达式,可以解析为 time、date、smalldatetime、datetime、datetime2 或 datetimeoffset 值。date 可以是表达式、列表达式、用户定义的变量或字符串文字。如果表达式是字符串文字,则它必须解析为一个 datetime 值。为避免不确定性,请使用四位数年份。有关两位数年份的信息,请参阅 two digit year cutoff 选项。
返回数据类型为 date 参数的数据类型,字符串文字除外。
字符串文字的返回数据类型为 datetime。如果字符串文字的秒数小数位数超过三位 (.nnn) 或包含时区偏移量部分,将引发错误。
返回值datepart 参数
dayofyear、day 和 weekday 返回相同的值。
每个 datepart 及其缩写都返回相同的值。
如果 datepart 为 month 且 date 月份比返回月份的天数多,因而 date 中的日在返回月份中不存在,则返回返回月份的最后一天。例如,9 月份有 30 天;因此,下面两个语句返回 2006-09-30 00:00:00.000:
SELECT DATEADD(month, 1, '2006-08-30')
SELECT DATEADD(month, 1, '2006-08-31')
number 参数
number 参数不能超出 int 的范围。在下面的语句中,number 的参数超出 int 范围 1。将返回如下错误消息:“将表达式转换为数据类型 int 时出现算术溢出错误。”
| 复制代码 |
| SELECT DATEADD(year,2147483648, '2006-07-31'); SELECT DATEADD(year,-2147483649, '2006-07-31'); |
date 参数
date 参数不能增加至其数据范围之外的值。在下面的语句中,与 date 值相加的 number 值超出了 date 数据类型的范围。将返回如下错误消息:“将值添加到 'datetime' 列导致溢出。”
| 复制代码 |
| SELECT DATEADD(year,2147483647, '2006-07-31'); SELECT DATEADD(year,-2147483647, '2006-07-31'); |
date 为 smalldatetime 型、datepart 为秒或秒小数部分时的返回值
smalldatetime 值的秒数部分始终为 00。如果 date 的数据类型为 smalldatetime,则适用以下准则:
- 如果 datepart 为 second 且 number 介于 -30 和 +29 之间,则不执行加法。
- 如果 datepart 为 second 且 number 小于 -30 或大于 +29,则以一分钟为起值执行加法。
- 如果 datepart 为 millisecond 且 number 介于 -30001 和 +29998 之间,则不执行加法。
- 如果 datepart 为 millisecond 且 number 小于 -30001 或大于 +29998,则以一分钟为起值执行加法。
DATEADD 可用在 SELECT <list>、WHERE、HAVING、GROUP BY 和 ORDER BY 子句中。
秒的小数部分精度
不允许将日期部分 microsecond 或 nanosecond 与数据类型为 smalldatetime、date 和 datetime 的 date 相加。
毫秒的小数位数为 3 (.123)。微秒的小数位数为 6 (.123456)。纳秒的小数位数为 9 (.123456789)。time、datetime2 和 datetimeoffset 数据类型的最大小数位数为 7 (.1234567)。如果 datepart 为 nanosecond,则 number 必须为 100 才能使 date 的秒小数部分增加。介于 1 和 49 之间的 number 向下舍入为 0,介于 50 和 99 之间的 number 向上舍入为 100。
以下语句加的 datepart 为 millisecond、microsecond 或 nanosecond。
| 复制代码 |
| DECLARE @datetime2 datetime2 = '2007-01-01 13:10:10.1111111' SELECT '1 millisecond' ,DATEADD(millisecond,1,@datetime2) UNION ALL SELECT '2 milliseconds', DATEADD(millisecond,2,@datetime2) UNION ALL SELECT '1 microsecond', DATEADD(microsecond,1,@datetime2) UNION ALL SELECT '2 microseconds', DATEADD(microsecond,2,@datetime2) UNION ALL SELECT '49 nanoseconds', DATEADD(nanosecond,49,@datetime2) UNION ALL SELECT '50 nanoseconds', DATEADD(nanosecond,50,@datetime2) UNION ALL SELECT '150 nanoseconds', DATEADD(nanosecond,150,@datetime2); /* Returns: 1 millisecond 2007-01-01 13:10:10.1121111 2 milliseconds 2007-01-01 13:10:10.1131111 1 microsecond 2007-01-01 13:10:10.1111121 2 microseconds 2007-01-01 13:10:10.1111131 49 nanoseconds 2007-01-01 13:10:10.1111111 50 nanoseconds 2007-01-01 13:10:10.1111112 150 nanoseconds 2007-01-01 13:10:10.1111113 */ |
时区偏移量
不允许对时区偏移量执行加法。
示例A. 以 1 为增量递增 datepart
下面的每条语句以 1 为增量递增 datepart。
| 复制代码 |
| DECLARE @datetime2 datetime2 = '2007-01-01 13:10:10.1111111' SELECT 'year', DATEADD(year,1,@datetime2) UNION ALL SELECT 'quarter',DATEADD(quarter,1,@datetime2) UNION ALL SELECT 'month',DATEADD(month,1,@datetime2) UNION ALL SELECT 'dayofyear',DATEADD(dayofyear,1,@datetime2) UNION ALL SELECT 'day',DATEADD(day,1,@datetime2) UNION ALL SELECT 'week',DATEADD(week,1,@datetime2) UNION ALL SELECT 'weekday',DATEADD(weekday,1,@datetime2) UNION ALL SELECT 'hour',DATEADD(hour,1,@datetime2) UNION ALL SELECT 'minute',DATEADD(minute,1,@datetime2) UNION ALL SELECT 'second',DATEADD(second,1,@datetime2) UNION ALL SELECT 'millisecond',DATEADD(millisecond,1,@datetime2) UNION ALL SELECT 'microsecond',DATEADD(microsecond,1,@datetime2) UNION ALL SELECT 'nanosecond',DATEADD(nanosecond,1,@datetime2); /* Year 2008-01-01 13:10:10.1111111 quarter 2007-04-01 13:10:10.1111111 month 2007-02-01 13:10:10.1111111 dayofyear 2007-01-02 13:10:10.1111111 day 2007-01-02 13:10:10.1111111 week 2007-01-08 13:10:10.1111111 weekday 2007-01-02 13:10:10.1111111 hour 2007-01-01 14:10:10.1111111 minute 2007-01-01 13:11:10.1111111 second 2007-01-01 13:10:11.1111111 millisecond 2007-01-01 13:10:10.1121111 microsecond 2007-01-01 13:10:10.1111121 nanosecond 2007-01-01 13:10:10.1111111 */ |
B. 在一条语句中将 datepart 增加一级以上
下面的每条语句将 datepart 与一个足够大的 number 相加,使得 date 的上一级 datepart 也增大。
| 复制代码 |
| DECLARE @datetime2 datetime2; SET @datetime2 = '2007-01-01 01:01:01.1111111'; --Statement Result ------------------------------------------------------------------- SELECT DATEADD(quarter,4,@datetime2); --2008-01-01 01:01:01.110 SELECT DATEADD(month,13,@datetime2); --2008-02-01 01:01:01.110 SELECT DATEADD(dayofyear,365,@datetime2); --2008-01-01 01:01:01.110 SELECT DATEADD(day,365,@datetime2); --2008-01-01 01:01:01.110 SELECT DATEADD(week,5,@datetime2); --2007-02-05 01:01:01.110 SELECT DATEADD(weekday,31,@datetime2); --2007-02-01 01:01:01.110 SELECT DATEADD(hour,23,@datetime2); --2007-01-02 00:01:01.110 SELECT DATEADD(minute,59,@datetime2); --2007-01-01 02:00:01.110 SELECT DATEADD(second,59,@datetime2); --2007-01-01 01:02:00.110 SELECT DATEADD(millisecond,1,@datetime2); --2007-01-01 01:01:01.110 |
C. 使用表达式作为 number 和 date 形参的实参
以下示例使用不同类型的表达式作为 number 和 date 形参的实参。
将列指定为 date
下例将每个 OrderDate 加上 2 天以计算新的 PromisedShipDate。
| 复制代码 |
| USE AdventureWorks; GO SELECT SalesOrderID ,OrderDate ,DATEADD(day,2,OrderDate) AS PromisedShipDate FROM Sales.SalesOrderHeader; |
将用户定义的变量指定为 number 和 date
下例将用户定义的变量指定为 number 和 date 的参数。
| 复制代码 |
| DECLARE @days int; DECLARE @datetime datetime; SET @days = 365; SET @datetime = '2000-01-01 01:01:01.111'; /* 2000 was a leap year */ SELECT DATEADD(day, @days, @datetime); |
将标量系统函数指定为 date
下例指定 SYSDATETIME 用作 date。
| 复制代码 |
| SELECT DATEADD(month, 1, SYSDATETIME()); |
将标量子查询和标量函数指定为 number 和 date
下例将标量子查询和标量函数 MAX(ModifiedDate) 用作 number 和 date 的参数。(SELECT TOP 1 ContactID FROM Person.Contact) 是 number 形参的假实参,用来说明如何从值列表中选择 number 实参。
| 复制代码 |
| USE AdventureWorks; GO SELECT DATEADD(month,(SELECT TOP 1 ContactID FROM Person.Contact), (SELECT MAX(ModifiedDate) FROM Person.Contact)); |
将常量指定为 number 和 date
下例将数值和字符常量用作 number 和 date 的参数。
SELECT DATEADD(minute, 1, ' 2007-05-07 09:53:01.0376635');
将数值表达式和标量系统函数指定为 number 和 date
下例将数值表达式 (-(10/2))、一元运算符 (-)、算术运算符 (/) 和标量系统函数 (SYSDATETIME) 用作 number 和 date 的参数。
| 复制代码 |
| SELECT DATEADD(month,-(10/2), SYSDATETIME()); |
将排名函数指定为 number
下例将排名函数用作 number 的参数。
| 复制代码 |
| USE AdventureWorks; GO SELECT c.FirstName, c.LastName ,DATEADD(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; |
将聚合开窗函数指定为 number
下例将聚合开窗函数用作 number 的参数。
| 复制代码 |
| USE AdventureWorks; GO SELECT SalesOrderID, ProductID, OrderQty ,DATEADD(day,SUM(OrderQty) OVER(PARTITION BY SalesOrderID),SYSDATETIME()) AS 'Total' FROM Sales.SalesOrderDetail WHERE SalesOrderID IN(43659,43664); GO |
参考
CAST 和 CONVERT (Transact-SQL)DATEDIFF (Transact-SQL)
http://msdn.microsoft.com/zh-cn/library/ms189794.aspx
返回指定的 startdate 和 enddate 之间所跨的指定 datepart 边界的计数(带符号的整数)。
有关所有 Transact-SQL 日期和时间数据类型及函数的概述,请参阅日期和时间数据类型及函数 (Transact-SQL)。 有关日期和时间数据类型及函数共有的信息和示例,请参阅使用日期和时间数据。
Transact-SQL 语法约定
语法| DATEDIFF ( datepart , startdate , enddate ) |
是指定所跨边界类型的 startdate 和 enddate 的一部分。 下表列出了所有有效的 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 |
是一个表达式,可以解析为 time、date、smalldatetime、datetime、datetime2 或 datetimeoffset 值。date 可以是表达式、列表达式、用户定义的变量或字符串文字。从 enddate 减去 startdate。
为避免不确定性,请使用四位数年份。 有关两位数年份的信息,请参阅two digit year cutoff 选项。
请参阅 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 子句中。
示例以下示例使用不同类型的表达式作为 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 |
参考
CAST 和 CONVERT (Transact-SQL)总结
以上是生活随笔为你收集整理的sql,dateadd,datediff的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇: 梦到儿子发生不好的事情了怎么回事
- 下一篇: 日本語趣味読み 一 星とり