SQL日期函数详解与实战

编写SQL中经常可以遇到日期的格式化与日期相关函数,这篇文章中我们将整理一下相关函数并给出一些实例供参考

获取时间函数

getdate()函数

getdate()函数获取当前的日期与时间。返回的为datetime类型

select GETDATE()

返回2020-09-21 10:07:38.170

SYSDATETIME()函数

SYSDATETIME()函数获取当前的日期与时间,但是返回的数据类型是DATETIME2,会更加精准,使用频率较少

SELECT SYSDATETIME()

格式化函数

CONVERT()函数

CONVERT() 函数是一个数据类型转化的通用函数,例如将数字类型转化为文本等。我们可以使用此函数把日期转换为新数据类型
语法为:

        CONVERT(data_type(length),expression,style)

其中data_type(length) 规定目标数据类型(带有可选的长度)。expression指需要转换的值。style 规定日期/时间的输出格式。

其中常用的style代码及显示格式如下:

        101: mm/dd/yyyy
        110: mm-dd-yyyy
        111: yyyy/mm/dd
        112: yyyymmdd
        120: yyyy-mm-dd hh:mm:ss
        121: yyyy-mm-dd hh:mm:sssssss

全部的style代码可以参考:https://www.cnblogs.com/rainman/p/6558261.html

例如;

    SELECT CONVERT(varchar(100), GETDATE(), 111)

通过查看转化后的数据类型,可以看到新的数据类型已变成varchar(100)类型。

--查看数据类型
DECLARE @query nvarchar(max) = 'SELECT CONVERT(varchar(100), GETDATE(), 111) AS [Column1]';
EXEC sp_describe_first_result_set @query, null, 0;

FORMAT()函数

Format函数用于指定显示的格式。
语法:

FORMAT(value,format[,culture])

参数format用于指定显示的格式,给予用户对格式更自由地控制,culture参数是可选的,用于指定显示的语言,该函数返回值的数据类型是NVARCHAR,如果格式转换失败,该函数返回NULL

参数format使用#表示一个数值,参数 format 使用以下占位符来表示日期/时间的格式:

1. yyyy、MM、dd:表示年、月、日
2. hh:mm:ss fffffff:表示时、分、秒、毫秒
3. 使用“/”,“-”等作为连接各个部分(part)的分割符号

例如要将当前日期转化为20200921,则SQL语句为:

SELECT Format(GETDATE(), 'yyyyMMdd')

同时format()函数还可以转变数值类型,使用特定的格式展示等

select FORMAT(123456789,'###-##-####') AS 'Custom Number Result'

对应返回结果为123-45-6789

日期的拆分与拼接(构造)

YEAR(date),MONTH(date),DAY(date)

YEAR(date),MONTH(date),DAY(date)等函数返回给定date的年,月,日
实例:

select year('2020-9-21'),month('2020-9-21'),day('2020-9-21')

DATEPART() 函数

DATEPART() 函数用于返回日期/时间的单独部分,比如年、月、日、小时、分钟等等

语法:

DATEPART(datepart,date)

其中date 参数是合法的日期表达式。datepart为需要取出的数据缩写代码。常用的datepart参数可以是下列的值:

    quarter:季度,取值范围是 1、2、3、4
    week:周在年中的序数,取值范围是 1 - 53
    dayofyear:天在年中的序数,取值范围是 1 - 366
    weekday:天在一周中的序数,取值范围是 1 - 7

全部参数可参阅:https://www.w3school.com.cn/sql/func_datepart.asp

具体实例代码:

--返回年,月份,季度,当前天数统计
SELECT DATEPART(yyyy,GETDATE()) AS Year,
DATEPART(m,GETDATE()) AS Month,
DATEPART(quarter,GETDATE()) AS Quarter,
DATEPART(dayofyear,GETDATE()) AS daynumber

DATENAME()函数,

与DATEPART不同的地方在于返回字符类型,比如Jan,一月等
语法:

DATENAME(datepart,date)

实例:

SELECT DATENAME(month, getdate()) AS 'Month'

对于中英文切换,使用如下语句:

set LANGUAGE 'Simplified Chinese'
select  DATENAME(WEEKDAY,getutcdate())

set LANGUAGE 'us_english'
select  DATENAME(WEEKDAY,getutcdate())

日期计算函数

EOMonth()函数

EOMonth()函数可以返回月份的最后一天。因此我们可以利用这个函数求某个月的最后一天与第一天。
语法:

EOMONTH(start_date [,month_to_add])

其中start_date: 有两种输入方式,能够转换为Date的字符串类型 和 date 数据类型
month_to_add: 是int 类型,能够为正整数,负整数和0,默认值是0,如果省略,那么使用默认值0,表示月份的偏移量。

--查看当前月的最后一天、下一个月的最后一天、上一个月的最后一天
declare @date date
set @date=getdate()

select EOMONTH(@date) as CurrentMonth_EndDay,
    EOMONTH(@date,1) as NextMonth_EndDay,
    EOMONTH(@date,-1) as LastMonth_EndDay

dateadd()函数

DATEADD() 函数在日期中添加或减去指定的时间间隔。
语法:

DATEADD(datepart,number,date)

其中datepart是單位(年,月,天等),number是指定的數值,date是原始日期
如下例的結果是当前时间的两个月后的日期,类型为datetime类型

    SELECT DATEADD(MONTH,2,getdate())

根据上述两个函数我们还可以通过上个月的最后一天+1来获取每个月第一天

select dateadd(day,1,EOMONTH(getdate(),-1)) as CurrentMonth_startDay

同时也可以通过前面所说的日期拼接函数与format函数实现

declare @date date
set @date=getdate()

select DATEFROMPARTS(year(@date),month(@date),1) 

--or

select FORMAT(GETDATE(),'yyyy-MM-01')

DATEDIFF()函数

DATEDIFF()函数计算两个日期之间的间隔,传回带正负符号的整数

语法:

DATEDIFF(datepart,startdate,enddate)

datepart为间隔的单位,可以选择天,周,月等。startdate跟enddate为起始时间

实例:

SELECT DATEDIFF(DAY, '2010-10-03','2010-10-04'  )

结果返回1

构造日期的函数

构造日期的函数有以下几个:
语法:

    DATEFROMPARTS ( year, month, day )
    DATETIME2FROMPARTS ( year, month, day, hour, minute, seconds, fractions, precision ) 
    DATETIMEOFFSETFROMPARTS ( year, month, day, hour, minute, seconds, fractions, hour_offset, minute_offset, precision )
    TIMEFROMPARTS ( hour, minute, seconds, fractions, precision ) 

传入对应参数后即可
其中参数precision 是指小数秒的精度,指的是DateTime2(n)、DateTimeOffset(n),Time(n)中的n值,表示以多少位小数表示1s,一般比较少使用

select DATEFROMPARTS ( 2020, 1, 2 )

练习实例

现有一列日期,请根据日期输出对应的每周开始与每周结束日期并格式化。
例如原始数据time_test表:

| date      | 
|-----------|
| 2020-8-4  | 
| 2020-8-5  | 
| 2020-8-6  | 
| 2020-8-12 | 
| 2020-8-8  | 
| 2020-8-12 | 
| 2020-9-15 |

期望的输出结果:

| date      | period  |
|-----------|---------|
| 2020-8-4  |0803-0809|
| 2020-8-5  |0803-0809|
| 2020-8-6  |0803-0809|
| 2020-8-12 |0810-0816|
| 2020-8-8  | 0803-0809|
| 2020-8-12 | 0803-0809|
| 2020-9-15 |0810-0816|

其中period的开始为每周周一,结束日期为每周周日

解答:
先给出代码

select [date],
format(DATEADD(wk, DATEDIFF(wk,0,DATEADD(dd,-1,[date])), 0),'MMdd')+'-'+format(DATEADD(dd,-1,DATEADD(wk, DATEDIFF(wk,0,DATEADD(dd,6,[date])), 0)),'MMdd') as period
from time_test

从内到外解析这一段代码,我们首先利用datediif(wk,0,date)计算从1900-01-01 到指定日期的周数。之后利用DateAdd函数在1900-01-01 的基础上加上刚刚我们计算出的周数,从而得到每周的开始时间。最后通过forma函数对日期格式化即可得出结果。

其中在最内层有一个DATEADD(dd,-1,[date]),这个是由于我使用的是英文版的SQL server,所以每周是周日开始与周六结束,如果使用中文版SQL server,应该就可以直接使[date]列

我的WX公众号:Romi的杂货铺,欢迎关注!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,117评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,963评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,897评论 0 240
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,805评论 0 203
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,208评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,535评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,797评论 2 311
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,493评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,215评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,477评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,988评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,325评论 2 252
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,971评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,055评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,807评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,544评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,455评论 2 266