sql server 中怎么自定义分割月功能
创始人
2024-12-23 11:02:30
0次

1、为何出现自定义分割月的需求

今天梳理一个平台的所有函数时,发现了一个自定义分割月函数,也就是指定分割月的开始日索引值(可以从1-31闭区间内的任何一个值)来获取指定日期所对应的分割月数值。这个函数当时是为了解决业务部门获取非标准月(标准月就是从每个月的第一天到最后一天组成一个完成的标准月份)的统计汇总数据的。例如:如果指定分割月的开始日索引值为5则表示某个月的5号到下个月的4号之间作为一个完整的分割月;同样地如果指定分割月的开始日索引值为1则表示标准月等等。

我仔细梳理了这个函数进行了重构简化以及扩展,该自定义分割月函数的实现区别之前写的SQL Server时间粒度系列----第3节旬、月时间粒度详解文章中将一个整数值和月份日期相互转换功能,这个是按照标准月来实现的,虽然思路大致相同,但是并没有针对之前的月份日期和整数值转换函数对来进行扩展而是独立开发新的功能函数。也是为了尽量做到函数功能职责单一性、稳定性、可维护性以及可扩展性。

2、sql server实现自定义分割月功能

自定义分割月功能函数包括两个标量函数:ufn_SegMonths和ufn_SegMonth3Date。ufn_SegMonths获取指定的日期在自定义分割月对应的分割月数值;ufn_SegMonth3Date获取指定一个分割月数值赌对应的月份日期。

sql server 版本的实现T-SQL代码如下:

IF OBJECT_ID(N'[dbo].[ufn_SegMonths]', 'FN') IS NOT NULLBEGIN  DROP FUNCTION [dbo].[ufn_SegMonths];ENDGO --==================================-- 功能:根据自定义月开始索引值获取指定日期所在的自定义月数。-- 说明:自定义分割月数 = 年整数值*100 + 当前所在分割月值。-- 环境:SQL Server 2005+。-- 调用:SET @intSegMonths = dbo.fn_SegMonths('2008-01-14', 15)。-- 创建:XXXX-XX-XX XX:XX-XX:XX XXX 创建函数实现。-- 修改:XXXX-XX-XX XX:XX-XX:XX XXX XXXXXXXX。--==================================CREATE FUNCTION [dbo].[ufn_SegMonths](   @dtmDate AS DATETIME            -- 日期  ,@tntSegStartIndexOfMonth AS INT = 15    -- 自定义分割月开始索引值(1-31))RETURNS INTASBEGIN    IF (@tntSegStartIndexOfMonth = 0 OR @tntSegStartIndexOfMonth >= 32)  BEGIN    SET @tntSegStartIndexOfMonth = 15;  END   DECLARE     @intYears AS INT    ,@tntMonth AS TINYINT    ,@sntDay AS SMALLINT;      SELECT     @intYears = DATEDIFF(YEAR, '1900-01-01', @dtmDate)    ,@tntMonth = DATEPART(MONTH, @dtmDate)    ,@sntDay = DATEPART(DAY, @dtmDate);   IF (@sntDay >= @tntSegStartIndexOfMonth)  BEGIN    SET @tntMonth = @tntMonth + 1;    END   IF (@tntMonth > 12)  BEGIN    SELECT       @intYears = @intYears + 1      ,@tntMonth = @tntMonth - 12;  END   RETURN @intYears * 100 + @tntMonth;ENDGO IF OBJECT_ID(N'[dbo].[ufn_SegMonths2Date]', 'FN') IS NOT NULLBEGIN  DROP FUNCTION [dbo].[ufn_SegMonths2Date];ENDGO --==================================-- 功能:获取自定义分割月数对应的自定义分割月日期。-- 说明:自定义分割月日期 = 自定义分割月数/100对应的年整数日期“组合”当前所在分割月值。-- 环境:SQL Server 2005+。-- 调用:SET @dtmSegMonthDate = dbo.fn_SegMonths2Date(11602)。-- 创建:XXXX-XX-XX XX:XX-XX:XX XXX 创建函数实现。-- 修改:XXXX-XX-XX XX:XX-XX:XX XXX XXXXXXXX。;--==================================CREATE FUNCTION [dbo].[ufn_SegMonths2Date](   @intSegMonths AS INT            -- 自定义分割月数)RETURNS DATETIMEASBEGIN      DECLARE @dtmDefaultBasedate AS DATETIME;  SET @dtmDefaultBasedate = '1900-01-01';   IF ((@intSegMonths IS NULL) OR (@intSegMonths <= 0))  BEGIN    RETURN @dtmDefaultBasedate;  END   DECLARE     @intYears AS INT    ,@intMonth AS INT;    SELECT     @intYears = @intSegMonths / 100    ,@intMonth = @intSegMonths % 100;     RETURN DATEADD(MONTH, @intMonth - 1, DATEADD(YEAR, @intYears, @dtmDefaultBasedate));ENDGO

3、测试验证效果

针对以上简单的测试代码如下:

DECLARE   @dtmStartDate AS DATETIME  ,@dtmEndDate AS DATETIME; SELECT   @dtmStartDate = '2000-01-01'  ,@dtmEndDate = '2016-12-31'; SELECT  [T1].*  ,[dbo].[ufn_SegMonths2Date]([T1].[SegMonths]) AS SegMonthDateFROM (  SELECT    [T].[CDate]    ,[dbo].[ufn_SegMonths]([T].[CDate], 28) AS SegMonths   FROM (    SELECT      DATEADD(DAY, [Num], @dtmStartDate) AS CDate    FROM      [dbo].[ufn_GetNums](0, DATEDIFF(DAY, @dtmStartDate, @dtmEndDate))  ) AS T  WHERE [T].[CDate] BETWEEN '2014-12-01' AND '2016-03-31') AS T1WHERE DATEPART(DAY, [T1].[CDate]) >= 27GO

相关内容

热门资讯

空调连续工作多久需要停机休息 空调连续工作的时间取决于多个因素,包括空调的型号、功率、使用环境和维护情况等。一般来说,空调可以连续...
空调哪个符号是除湿的 空调除湿功能通常用一个水滴形状的符号表示。不同品牌和型号的空调遥控器可能会有所差异,但一般来说,除湿...
格力空调多长时间加一次氟利昂 1、一般情况下,空调对氟利昂的使用量是非常小的,所以在空调使用了四年左右的时候再考虑加也没问题。2、...
空调用多长时间需要加氟一次 一般情况下是五年。当出现以下这几种情况时,空调才需要加氟。1、空调的室内机和室外机各有两个接口,当接...
格调生活·C标思享荟:卡萨帝在... 9月12日的郑州龙湖金融岛,夜风轻拂,灯光璀璨。“C标时刻共传奇——卡萨帝思享荟暨20周年品牌盛典郑...
品牌价值破千亿、高端份额持续领... 9月12日,“C标时刻共传奇——卡萨帝思享荟暨20周年品牌盛典郑州站”在郑州龙湖金融岛举办。2026...
空调主板坏了修800还是换新的 空调主板坏了是修还是换新,需要考虑多个因素,以下是一些建议:1. 维修成本:如果维修费用较低,比如 ...
空调开多久需要休息多长时间 问题:空调开多久需要休息多长时间回答:1、在使用空调的过程中,一般空调开7~8个小时左右需要休息2~...
中央空调多长时间清洗一次 1、一般空调开机前清洗一次即可,空调开机中间时段再清洗一次,空调关机时清洗一次,这样比较合理。2、空...
中央空调氟利昂多久加一次 看空调制热和制冷程度,很多人的观点认为氟利昂必须一年放一次,其实这个观点是错误的,理解上面有点偏差,...