SQL Server时间粒度系列----第4节季、年时间粒度详解

本文目录列表:
 
SQL Serve季时间粒度
 
    季时间粒度也即是季度时间粒度。一年每3个月是一个季,一年共4季,1月到3月是第1季、4月到6月是第2个季、依次顺延。季也是日期时间范围的,我们也会引入季基准日期,也就是每个季度的第一天。以下提供季基准日期和整数相互转换的功能的实现,还有获取指定日期时间所在当前年内的季索引,从1开始计数,包括1、2、3、4。
 
    提供季基准日期和整数相互转换的功能函数,T-SQL代码如下:
 1 IF OBJECT_ID(N'dbo.ufn_Quarters', 'FN') IS NOT NULL
 2 BEGIN
 3     DROP FUNCTION dbo.ufn_Quarters;
 4 END
 5 GO
 6  
 7 --==================================
 8 -- 功能: 获得指定日期时间基于基准日期的总季数(一个整数值)
 9 -- 说明: 如果指定的日期时间为NULL或者小于基准日期“1900-01-01”时,则其值默认基准日期
10 --       结果值为非负整数,从0开始计数。
11 -- 作者: XXX
12 -- 创建: yyyy-MM-dd
13 -- 修改: yyyy-MM-dd XXX 修改内容描述
14 -- 调用: SET @sintQuarters = dbo.ufn_Quarters('2008-01-14')
15 --==================================
16 CREATE FUNCTION dbo.ufn_Quarters
17 (
18     @dtmDate DATETIME                    -- 指定的日期时间
19 ) RETURNS SMALLINT
20     --$Encode$--
21 AS
22 BEGIN
23     SET @dtmDate = dbo.ufn_GetValidDate(@dtmDate);
24  
25     -- datepart参数也可以为qq或q
26     RETURN DATEDIFF(QUARTER, '1900-01-01', @dtmDate);
27 END
28 GO
29  
30 IF OBJECT_ID(N'dbo.ufn_Quarters2Date', 'FN') IS NOT NULL
31 BEGIN
32     DROP FUNCTION dbo.ufn_Quarters2Date;
33 END
34 GO
35  
36 --==================================
37 -- 功能: 获得一个整数值基于基准日期对应的季基准日期
38 -- 说明: 如果指定的整数值为NULL或为负整数时,则其值默认为0;
39 --       如果指定的整数值大于“9999-12-31”对应的整数值时,则其值默认设置为“9999-12-31”对应的整数值;
40 --       结果值为从基准日期开始计数的日期;
41 --       季基准日期是指所在季度的第一个月份中第1天对应的日期,比如'2016-06-08'月份的姐旬基准日期为'2016-04-01'。
42 -- 作者: XXX
43 -- 创建: yyyy-MM-dd
44 -- 修改: yyyy-MM-dd XXX 修改内容描述
45 -- 调用: SET @dtmDate = dbo.ufn_Quarters2Date(300) --'1975-02-21'
46 --==================================
47 CREATE FUNCTION dbo.ufn_Quarters2Date 
48 (
49     @sintQuarters SMALLINT
50 ) RETURNS DATETIME
51     --$Encode$--
52 AS
53 BEGIN
54     SET @sintQuarters = dbo.ufn_GetValidDateNum(@sintQuarters);
55  
56     DECLARE @sintMaxQuarters AS SMALLINT;
57     SET @sintMaxQuarters = dbo.ufn_Quarters('9999-12-31');
58  
59     IF @sintQuarters >= @sintMaxQuarters
60     BEGIN
61         SET @sintQuarters = @sintMaxQuarters;
62     END
63  
64     -- datepart参数也可以为qq或q
65     RETURN DATEADD(QUARTER, @sintQuarters, '1900-01-01')
66 END
67 GO

 

  
    获取指定日期时间在当前年的旬索引的功能函数,T-SQL代码如下:
 1 IF OBJECT_ID(N'dbo.ufn_QuarterOfYear', 'FN') IS NOT NULL
 2 BEGIN
 3     DROP FUNCTION dbo.ufn_QuarterOfYear;
 4 END
 5 GO
 6 
 7 --==================================
 8 -- 功能: 获取指定的日期时间所在当前年内的旬索引
 9 -- 说明: 结果从1开始计数,1、2、3、4分别表示第1季度、第2季度、第3季度、第4季度。
10 -- 作者: XXX
11 -- 创建: yyyy-MM-dd
12 -- 修改: yyyy-MM-dd XXX 修改内容描述
13 -- 调用: SET @tintQuarterOfYear = dbo.ufn_QuarterOfYear('2016-01-11');
14 --==================================
15 CREATE FUNCTION dbo.ufn_QuarterOfYear
16 (
17     @dtmDate DATETIME                --指定的日期时间
18 ) RETURNS TINYINT
19     --$Encode$--
20 AS
21 BEGIN
22     -- datepart参数也可以为qq或q
23     RETURN DATEPART(QUARTER, @dtmDate);
24 END
25 GO

 

    测试以上三个功能函数的效果,T-SQL代码如下:
 1 DECLARE @dtmDate AS DATETIME;
 2 SET @dtmDate = '2016-01-11';
 3  
 4 SELECT @dtmDate AS 'The Current Date'
 5     ,dbo.ufn_Quarters(@dtmDate) AS 'The Total Of Quarters Base-on Basedate"1900-01-01"'
 6     ,dbo.ufn_Quarters2Date(dbo.ufn_Quarters(@dtmDate)) AS 'Quarter Basedate Mapping'
 7     ,dbo.ufn_QuarterOfYear(@dtmDate) AS 'The Quarter IndexID,Starting With 1';
 8  
 9 SET @dtmDate = '2016-09-11';
10  
11 SELECT @dtmDate AS 'The Current Date'
12     ,dbo.ufn_Quarters(@dtmDate) AS 'The Total Of Quarters Base-on Basedate"1900-01-01"'
13     ,dbo.ufn_Quarters2Date(dbo.ufn_Quarters(@dtmDate)) AS 'Quarter Basedate Mapping'
14     ,dbo.ufn_QuarterOfYear(@dtmDate) AS 'The Quarter IndexID,Starting With 1'
15 GO
16   

    执行后的查询结果如下图

 
SQL Server年时间粒度
 
    年时间粒度很容易理解的,在SQL Server提供的有关日期时间数据类型中,能够支持日期部分的最大范围区间是[0000-01-01,9999-12-31],那么指定日期在这个日期范围的年索引是从1开始,包括1、2、3、……、9998、9999。年基准日期也即是当前年的第一天,比如"2016-01-11"所在当前年的年基准日期是”2016-01-01“,提供年基准日期和整数相互转换的功能函数实现。
    
    获取指定的日期时间所在日期的年索引的功能函数,T-SQL代码如下:
 1 IF OBJECT_ID(N'dbo.ufn_YearOfDate', 'FN') IS NOT NULL
 2 BEGIN
 3     DROP FUNCTION dbo.ufn_YearOfDate;
 4 END
 5 GO
 6  
 7 --==================================
 8 -- 功能: 获取指定的日期时间所在日期内的年索引
 9 -- 说明: 结果从1开始计数,1、2、3、……、9998、9999。
10 -- 作者: XXX
11 -- 创建: yyyy-MM-dd
12 -- 修改: yyyy-MM-dd XXX 修改内容描述
13 -- 调用: SET @sintYearOfDate = dbo.ufn_YearsOfDate('2016-01-11');
14 --==================================
15 CREATE FUNCTION dbo.ufn_YearOfDate
16 (
17     @dtmDate DATETIME                --指定的日期时间
18 ) RETURNS SMALLINT
19     --$Encode$--
20 AS
21 BEGIN
22     RETURN YEAR(@dtmDate);
23 END
24 GO
25  

 

    提供年基准日期和整数相互转换的功能函数,T-SQL代码如下:
 1 IF OBJECT_ID(N'dbo.ufn_Years', 'FN') IS NOT NULL
 2 BEGIN
 3     DROP FUNCTION dbo.ufn_Years;
 4 END
 5 GO
 6  
 7 --==================================
 8 -- 功能: 获得指定日期时间基于基准日期的总年数(一个整数值)
 9 -- 说明: 如果指定的日期时间为NULL或者小于基准日期“1900-01-01”时,则其值默认基准日期
10 --       结果值为非负整数,从0开始计数。
11 -- 作者: XXX
12 -- 创建: yyyy-MM-dd
13 -- 修改: yyyy-MM-dd XXX 修改内容描述
14 -- 调用: SET @intMonths = dbo.ufn_Years('2008-01-14')
15 --==================================
16 CREATE FUNCTION dbo.ufn_Years 
17 (
18     @dtmDate DATETIME            -- 指定的日期时间
19 ) RETURNS SMALLINT
20     --$Encode$--
21 AS
22 BEGIN
23     SET @dtmDate = dbo.ufn_GetValidDate(@dtmDate);
24  
25     -- datepart参数也可以为yy或yyyy
26     RETURN DATEDIFF(YEAR, '1900-01-01', @dtmDate)
27 END
28 GO
29  
30 IF OBJECT_ID(N'dbo.ufn_Years2Date', 'FN') IS NOT NULL
31 BEGIN
32     DROP FUNCTION dbo.ufn_Years2Date;
33 END
34 GO
35  
36 --==================================
37 -- 功能: 获得一个整数值基于基准日期对应的年基准日期
38 -- 说明: 如果指定的整数值为NULL或为负整数时,则其值默认为0;
39 --       如果指定的整数值大于“9999-12-31”对应的整数值时,则其值默认设置为“9999-12-31”对应的整数值;
40 --       结果值为从基准日期开始计数的日期;
41 --       年基准日期是指所在年的第一个月份中第1天对应的日期,比如'2016-06-08'月份的姐旬基准日期为'2016-01-01'。
42 -- 作者: XXX
43 -- 创建: yyyy-MM-dd
44 -- 修改: yyyy-MM-dd XXX 修改内容描述
45 -- 调用: SET @dtmDate = dbo.ufn_Years2Date(300) --'1975-02-21'
46 --==================================
47 CREATE FUNCTION dbo.ufn_Years2Date
48 (
49     @sintYears SMALLINT
50 ) RETURNS DATETIME
51     --$Encode$--
52 AS
53 BEGIN
54     SET @sintYears = dbo.ufn_GetValidDateNum(@sintYears);
55  
56     DECLARE @sintMaxYears AS SMALLINT;
57     SET @sintMaxYears = dbo.ufn_Years('9999-12-31');
58  
59     IF @sintYears >= @sintMaxYears
60     BEGIN
61         SET @sintYears = @sintMaxYears;
62     END
63  
64     -- datepart参数也可以为yy或yyyy
65     RETURN DATEADD(YEAR, @sintYears, '1900-01-01')
66 END
67 GO

    

    测试以上3个功能函数的效果,T-SQL代码如下:
 1 DECLARE @dtmDate AS DATETIME;
 2 SET @dtmDate = '2016-01-11';
 3  
 4 SELECT @dtmDate AS 'The Current Date'
 5     ,dbo.ufn_Years(@dtmDate) AS 'The Total Of Years Base-on Basedate"1900-01-01"'
 6     ,dbo.ufn_Years2Date(dbo.ufn_Years(@dtmDate)) AS 'Year Basedate Mapping'
 7     ,dbo.ufn_YearOfDate(@dtmDate) AS 'The Year IndexID,Starting With 1';
 8  
 9 SET @dtmDate = '2016-09-11';
10  
11 SELECT @dtmDate AS 'The Current Date'
12     ,dbo.ufn_Years(@dtmDate) AS 'The Total Of Years Base-on Basedate"1900-01-01"'
13     ,dbo.ufn_Years2Date(dbo.ufn_Years(@dtmDate)) AS 'Year Basedate Mapping'
14     ,dbo.ufn_YearOfDate(@dtmDate) AS 'The Year IndexID,Starting With 1';
15 GO

 

     执行后的查询结果如下图

 
总结语
    
    本文主要提供了季和年这两个时间粒度的讲解,也分别提供的其基准日期和整数相互转换的功能实现,还有各自有关的索引功能函数。之前的博文也有获取比如旬内日索引、月内日索引、月内旬索引等等的相关功能函数,这些都不是基于基准日期”1900-01-01“,都是在SQL Server能支持的最大的日期部分的范围区间【0001-01-01,9999-12-31】的。
    
    以上有关季和年有关的功能函数,使用了ufn_GetValidDate和ufn_GetValidDateNum这两个通用同能函数,可以参考SQL Server时间粒度系列----第3节旬、月时间粒度详解,里面有具体的实现。
 
参考清单列表

1、https://msdn.microsoft.com/zh-cn/library/ms186819(v=sql.90).aspx

 

posted @ 2016-01-11 10:55  剑走江湖  阅读(760)  评论(0编辑  收藏  举报