SQL Server时间粒度系列----第1节时间粒度概述
本文目录列表:
我们知道比如年、季度、月、旬(一个月分为上中下3旬)、日这样的时间单位;也知道小时、分钟、秒;也有短于秒的比如毫秒、微妙、纳秒、飞秒等等时间单位。基于不同的时间,我们可以将时间粒度看作不同时间单位的时间值。
举个例子来说明时间粒度这个问题。一个日期时间值是'2016-02-29',很显然我们知道这个日期所对应的年、月、日分别为2016年、2月和29日,这个29日就是2016年2月第29天(日)。我们也可以继续根据这个日期时间值发问以下的问题:此日期属于2016年第几周?此日期属于所在周的星期几?此日期属于2016年2月的那个旬?此日期属于2016年的第几季度?此日期 又属于所在季度的第几天?此日期属于2016年的上半年还是下半年?此日期属于2016年的第几天?……
有些公司会有自己公司特殊的财务处理周期时间段,比如说:4个月、4个月、3个月为不同时间段的财务处理周期。
我们来看看SQL Server提供了那些日期时间数据类型,smalldatetime和datetime(SQL Server 2005提供的),后来在SQL Server 2008又新增了date、time、datetime2和datetimeoffset共4个数据类型。以上6种日期时间数据类型用法和区别请参考日期和时间数据类型及函数 (Transact-SQL)。
SQL Server针对这些日期时间数据类型的具体一个日期时间值都能得到那些时间粒度呢?我们可以通过datepart函数(https://msdn.microsoft.com/zh-cn/library/ms189794(v=sql.90).aspx和https://msdn.microsoft.com/zh-cn/library/ms174420(v=sql.100).aspx)可以知道。下面的表格汇总了datepart函数将获得指定日期时间值的哪些时间粒度值:
日期部分
|
缩写
|
SQL Server运行版本
|
year
|
yy,yyyy
|
SQL Server 2005 +
|
quarter |
qq,q
|
SQL Server 2005 +
|
month
|
mm,m
|
SQL Server 2005 +
|
dayofyear
|
dy,y
|
SQL Server 2005 +
|
day
|
dd,d
|
SQL Server 2005 +
|
week
|
wk,ww
|
SQL Server 2005 +
|
weekday
|
dw |
SQL Server 2005+
|
hour
|
hh
|
SQL Server 2005 +
|
minute
|
mi,n
|
SQL Server 2005 +
|
second
|
ss,s
|
SQL Server 2005 +
|
millisecond
|
ms
|
SQL Server 2005 +
|
microsecond
|
mcs
|
SQL Server 2008 +
|
nanosecond
|
ns
|
SQL Server 2008 +
|
TZoffset
|
tz
|
SQL Server 2008 +
|
ISO_WEEK
|
isowk,isoww
|
SQL Server 2008 +
|
注意:SQL Server 2005 +表示的意思是:SQL Server 2005以及SQL Server 2005以上版本。
1、日期以上时间粒度的T-SQL代码如下:
1 -- 日期以上时间粒度的T-SQL代码: 2 DECLARE @dtmCreateTime AS DATETIME; 3 SET @dtmCreateTime = '2016-02-29 23:59:59.997'; 4 SELECT DATEPART(YEAR, @dtmCreateTime) AS 'Year,yy,yyyy CurrentYear'; 5 SELECT DATEPART(QUARTER, @dtmCreateTime) AS 'Quarter,qq,q CurrentQuarter'; 6 SELECT DATEPART(MONTH, @dtmCreateTime) AS 'Month,mm,m CurrentMonth'; 7 SELECT DATEPART(DAYOFYEAR, @dtmCreateTime) AS 'DayOfYear,dy,y DayOfCurrentYear'; 8 SELECT DATEPART(DAY, @dtmCreateTime) AS 'Day,dd,d DayOfCurrentMonth'; 9 SELECT DATEPART(WEEK, @dtmCreateTime) AS 'Week,wk,ww WeekOfCurrentYear', @@DATEFIRST AS 'FisrtDayOfWeek[可以为1到7,sunday对应的7]', DATEPART(WEEKDAY, @dtmCreateTime) AS 'Weekday,dw WeekdayOfCurrentWeek', DATENAME(WEEKDAY, @dtmCreateTime) AS 'WeekdayName'; 10 GO
执行后的查询结果如下:
2、时间以下的时间粒度的T-SQL代码:
1 -- 时间以下时间粒度的T-SQL代码: 2 DECLARE @dtmCreateTime AS DATETIME; 3 SET @dtmCreateTime = '2016-02-29 23:59:59.997'; 4 SELECT DATEPART(HOUR, @dtmCreateTime) AS 'Hour,hh HourOfDay', DATEPART(MINUTE, @dtmCreateTime) AS 'Minute,mi,n MinuteOfDay', DATEPART(SECOND, @dtmCreateTime) AS 'Second,ss,s SecondOfDay', DATEPART(MILLISECOND, @dtmCreateTime) AS 'Millisecond,ms MillisecondOfDay'; 5 SELECT DATEPART(MICROSECOND, @dtmCreateTime) AS 'Mircosecond,mcs MicrosecondOfDay', DATEPART(NANOSECOND, @dtmCreateTime) AS 'Nanosecond,ns NanosecondOfDay'; 6 GO
执行后的查询结果如下:
3、时区偏移TZOFFSET时间粒度的T-SQL代码:
1 -- 时区偏移TZOFFSET时间粒度的T-SQL代码: 2 DECLARE @dtmofsDateTime AS DATETIMEOFFSET; 3 SET @dtmofsDateTime = '2007-05-10 00:00:01.1234567 +05:10' 4 SELECT DATEPART (TZOFFSET, @dtmofsDateTime) AS 'TZoffset,tz TZoffsetMinuteTotal'; 5 GO
执行后的查询结果如下:
4、 ISO_WEEK时间粒度的T-SQL代码:
1 -- ISO_WEEK时间粒度的T-SQL代码: 2 SELECT DATEPART(ISO_WEEK, '2016-01-06') AS 'ISO_WEEK,isowk,isoww ISO_WeekValue' 3 GO
执行后的查询结果如下:
注意:以下文字摘抄自SQL Server联机帮助,具体请参考:https://msdn.microsoft.com/zh-cn/library/ms174420(v=sql.100).aspx
ISO 8601 包括 ISO 周-日期系统,即周的编号系统。每周都与该周内星期四所在的年份关联。例如,2004 年第 1 周 (2004W01) 从 2003 年 12 月 29 日星期一到 2004 年 1 月 4 日星期天。一年中最大的周数可能为 52 或 53。这种编号方式通常用于欧洲国家/地区,但其他国家/地区很少用到。
不同的国家/地区的编号系统可能不符合 ISO 标准。现在至少可能存在六种编号系统,如下表所示:
每周的第一天 |
一年的第一周包含 |
分配两次的周 |
使用的国家/地区 |
---|---|---|---|
星期日 |
1 月 1 日, 第一个星期六, 其中有 1–7 天属于此年 |
是 |
美国 |
星期一 |
1 月 1 日, 第一个星期日, 其中有 1–7 天属于此年 |
是 |
大多数欧洲国家和英国 |
星期一 |
1 月 4 日, 第一个星期四, 其中有 4-7 天属于此年 |
否 |
ISO 8601,挪威和瑞典 |
星期一 |
1 月 7 日, 第一个星期一, 7 天均属于此年 |
否 |
|
星期三 |
1 月 1 日, 第一个星期二, 其中有 1–7 天属于此年 |
是 |
|
星期六 |
1 月 1 日, 第一个星期五, 其中有 1–7 天属于此年 |
是 |
|
我们执行下面的T-SQL代码:
1 SELECT DATEPART(YEAR, 0) AS 'BaseDateYear', DATEPART(MONTH, 0) AS 'BaseDateMonth', DATEPART(DAY, 0) AS 'BaseDateDay'; 2 SELECT YEAR(0) AS 'BaseDateYear', MONTH(0) AS 'BaseDateMonth', DAY(0) AS 'BaseDateDay'; 3 GO
执行后的查询结果如下:
从上面的查询结果我们可以知道datepart(year, @dtmDateTime)、datepart(month, @dtmDateTime)、datepart(day, @dtmDateTime)分别与year(@dtmDateTime)、month(@dtmDateTime)、day(@dtmDateTime)获得的结果值相同。这个日期“1900-01-01”就是SQL Server提供的基准日期(SQL Server联机帮助成为基准年)。有关这个基准日期的一种特殊用法,就是数据表设计的一种方法消除NULL,将字段设置为NOT NULL加默认值。针对日期时间数据类型字段列的默认值就可以设置为这个“1900-01-01”基准日期。
SQL Server提供的datetime日期时间数据类型,内部使用两个4字节的整数来存储该数据值。第一个4字节存储”基准日期“(即1900年1月1日)之前或之后的天数。基准日期是系统参照日期。另一个4字节存储天的时间,以午夜后经过的1/300秒数表示。SQL Server引擎也是以“1900-01-01”这个基准日期来参考使用的。具体的请参考日期和时间 (Transact-SQL)。
后面的博文会更多的使用这个基准日期的。
我们在本文中了解了有关时间粒度的概述,还有SQL Server提供了那些类型的时间粒度,以及各个时间粒度的T-SQL代码演示,最后我们知道SQL Server 提供了一个基准日期(基准年)“1900-01-01“。