前言
在编写sql的时候,会碰到对日期的处理,特别是日期区间对业务数据的限制。
如:用户数据的是一个固定月份 2020-03 这个时候需要匹配数据就是2020-03-01 ~ 2020-03-31的数据。对于此类处理,就需要编写sql的人员进行运算转化出两个日期去限制数据区间了。
网上搜了一些处理方式,大部分都是拼接而成,在各种比较下,如下的处理方式比较合理与准确。
--当前日期
select getdate() CurrentDate;
--当月第一天
select dateadd(day,-day(getdate())+1,getdate()) current_Month_FirstDay;
--当月最后一天
select dateadd(month,datediff(month,0,dateadd(month,1,getdate())),-1) current_Month_EndDay;
--当年第一天
select dateadd(YEAR,datediff(YEAR,0,getdate()),0) current_Year_FirstDay;
--当年最后天
select dateadd(YEAR,datediff(YEAR,0,dateadd(YEAR,1,getdate())),-1) current_Year_EndDay;
--下年第一天
select dateadd(YEAR,datediff(YEAR,0,dateadd(YEAR,1,getdate())),0) next_Year_Firstday;
--下年最后一天
select dateadd(YEAR,datediff(YEAR,0,dateadd(YEAR,2,getdate())),-1) next_Year_Endday;
--上年第一天
select dateadd(YEAR,datediff(YEAR,0,dateadd(YEAR,-1,getdate())),0) last_Year_Firstday;
--上年最后一天
select dateadd(YEAR,datediff(YEAR,0,getdate()),-1) last_Year_Endday;
解释:
0
表示1990-01-01,
datediff(YEAR,0,getdate())
表示1990到当前日期是多少年
dateadd(YEAR,datediff(YEAR,0,getdate()),0)
表示从1990年加datediff(YEAR,0,getdate()) 年,刚好就是当前日期所在年度的一月一号
其他的几种表示方式,以此思路类推,包括month,day等关键词
介绍两个重要的函数(DATEDIFF 、DATEADD)
DATEDIFF (Transact-SQL)
此函数返回指定的 startdate 和 enddate 之间所跨的指定 datepart 边界的计数(作为带符号整数值) 。
语法
DATEDIFF ( datepart , startdate , enddate )
1、参数 datepart
DATEDIFF 用于报告 startdate 与 enddate 之间差异的单位。 常用 datepart 单位包括 month 或 second。
datepart 值不能在变量中指定,也不能指定为带引号的字符串,如 ‘month’。
下表列出了所有有效的 datepart 值 。 DATEDIFF 接受 datepart 的全名或任何列出的全名缩写形式。
datepart name 名称 | datepart abbreviation 缩写 |
---|---|
year | yy yyyy yyyyyy |
quarter | q qq qqq |
month | m mm mmm |
dayofyear | dy ydy y |
day | d dd ddd |
week | wk wwwk ww |
hour | hhhh |
minute | mi nmi n |
second | s ss sss |
millisecond | ms |
microsecond | mcs |
nanosecond | ns |
startdate
可解析为下列值之一的表达式:
date
datetime
datetimeoffset
datetime2
smalldatetime
time
enddate
请参阅 startdate 。
2、返回值类型 int
startdate 与 enddate 之间的 int 差异,以 datepart 设置的边界表示 。
例如,SELECT DATEDIFF(day, ‘2036-03-01’, ‘2036-02-28’); 返回 -2,提示 2036 必须为闰年。 这种情况意味着如果从 startdate ‘2036-03-01’ 开始,然后计数 -2 天,则会得到 enddate ‘2036-02-28’。
若 bigint 的返回值超出范围(-2,147,483,648 到 +2,147,483,647),DATEDIFF 返回错误 。 对于 millisecond,startdate 和 enddate 之间的最大差值为 24 天 20 小时 31 分钟 23.647 秒 。 对于 second,最大差值为 68 年 19 天 3 小时 14 分 7 秒 。
如果为 startdate 和 enddate 都只指定了时间值,并且 datepart 不是时间 datepart,则 DATEDIFF 返回 0 。
DATEDIFF 使用 startdate 或 enddate 的时区偏移部分来计算返回值。
由于 smalldatetime 仅精确到分钟,因此在 startdate 或 enddate 具有 smalldatetime 值时,返回值中的秒和毫秒将始终设置为 0 。
如果只为某个日期数据类型变量指定时间值,DATEDIFF 会将所缺日期部分的值设置为默认值:1900-01-01。 如果只为某个时间或日期数据类型的变量指定日期值,DATEDIFF 会将所缺时间部分的值设置为默认值:00:00:00。 如果 startdate 和 enddate 中有一个只含时间部分,另一个只含日期部分,DATEDIFF 会将所缺时间和日期部分设置为各自的默认值 。
如果 startdate 和 enddate 具有不同的日期数据类型,并且其中一个的时间部分或秒小数部分精度比另一个高,DATEDIFF 会将另一个的所缺部分设置为 0 。
示例:
SELECT DATEDIFF(day, '2020-01-01', '2020-02-01');
结果:31
说明2020-01-01到2020-02-01 是31天
SELECT DATEDIFF(YEAR, 0, '2020-01-01');
结果:120
这个说明是1900到2020是120年
SELECT DATEDIFF(MONTH, 0, '2020-01-01');
结果:1440
这个说明是1900到2020是1440个月
其他类型以此类推
DATEADD (Transact-SQL)
语法
DATEADD (datepart , number , date )
参数 datepart
DATEADD 要将其与整数值相加的 date 的一部分 。 此表列出了所有有效的 datepart 参数 。
datepart name 名称 | datepart abbreviation 缩写 |
---|---|
year | yy yyyy |
quarter | q qq |
month (月) | m mm |
minute (分钟) | mi n |
dayofyear | dy y |
day | d dd |
week | wk ww |
weekday | dw w |
hour | hhhh |
second | s ss |
millisecond | ms |
microsecond | mcs |
nanosecond | ns |
number
一个表达式,可解析为 DATEADD 将其与 date 的 datepart 相加的 int 。 对于 number,DATEADD 接受 用户定义的变量值 。 DATEADD 将截断带小数部分的指定 number 值 。 在这种情况下,它不对 number 值进行舍入 。
date
可解析为下列值之一的表达式:
•date
•datetime
•datetimeoffset
•datetime2
•smal ldatetime
•time
返回类型
此方法的返回值数据类型是动态的。 返回类型取决于为 date 提供的参数。 如果 date 的值是字符串文本日期,则 DATEADD 返回日期/时间值 。 如果为 date 提供了其他的有效输入数据类型,则 DATEADD 返回相同的数据类型。 如果字符串文本秒数小数位超过三位 (.nnn) 或如果字符串文本包含时区偏移量部分,则 DATEADD 引发错误。
示例:
SELECT DATEADD(month, 1, '2020-08-30');
结果:2020-09-30 00:00:00
说明 2020-08-30加了一个月
SELECT DATEADD(year, 1, '2020-02-03');
结果:2021-02-03 00:00:00
说明2020-02-03加了一年