您的位置:澳门新葡萄京娱乐网站 > 编程知识 > SQL Server时间粒度系列----第8节位运算以致安装日

SQL Server时间粒度系列----第8节位运算以致安装日

2019-12-22 01:30
/*创建日期类型记录表格*/CREATE TABLE `tb_workday`  NOT NULL AUTO_INCREMENT,`exact_date` varchar NOT NULL COMMENT '具体日期:格式date',`date_year` varchar NOT NULL COMMENT '具体日期:格式date',`date_type` tinyint NOT NULL COMMENT '日期类型:0、工作日;1、特殊工作日;2、法定节假日',PRIMARY KEY  ENGINE=InnoDB AUTO_INCREMENT=829 DEFAULT CHARSET=utf8 COMMENT='各年工作日&法定节假日数据'

 $_date) { $_ret = 0; $_date = date('Ymd', strtotime; $_post_data = array; $_ret_curl = curl_post; $_ret_curl = json_decode; //工作日 if ($_ret_curl['data'] == 0) { $dateData['exact_date'] = $_date; $dateData['date_year'] = $year; $dateData['date_type'] = 0; $_ret = $m->add ? 1 : 0; unset; //工作日 判断是否为周末 if (in_array(self::get_week) { //特殊工作日 $dateData['exact_date'] = $_date; $dateData['date_year'] = $year; $dateData['date_type'] = 1; $_ret = $m->add ? 1 : 0; unset; } } //法定节假日 if ($_ret_curl['data'] == 2) { $dateData['exact_date'] = $_date; $dateData['date_year'] = $year; $dateData['date_type'] = 2; $_ret = $m->add ? 1 : 0; unset; } //休息日 暂不处理 /*if ($_ret_curl['data'] == 1) { }*/ $_ret && $count  ; unset($_date, $_post_data, $_ret_curl, $_ret); } return $count; } /** * 获取当年所有工作日  * @param string $year 当年年份 * @return array */ private function getWorkDays { $m = M; $map['date_year'] = $year; $map['date_type'] = 0; $DateArray = $m->field->where; if  { $DateArray = array_column($DateArray, 'exact_date'); return $DateArray; } else { //更新数据库工作日数据 $ret = self::updateDate { return self::getWorkDays; } else { return false; } } } /** * 获取开始日期后第N个工作日具体日期 * @param $startdate string 计算开始日期 需包含年月日信息 * @param $days int 间隔天数 * @return mixed 成功返回 对应日期,失败返回false */ public function getNextWorkDate { $year = date('Y', strtotime; $startdate = date('Y-m-d', strtotime; $workDays = $this->getWorkDays; $search_key = array_search(date('Ymd', strtotime, $workDays); if ($search_key === false) {//查询日期为非工作 //获取查询日期前最近工作日 $m = M; $map['date_year'] = $year; $map['date_type'] = 0; $map['DATE_FORMAT(`exact_date`,'%Y-%m-%d')'] = array; $_search_date = $m->where->order->getField; $search_key = array_search($_search_date, $workDays); unset($m, $map, $_search_date); } $t_key = $search_key   $days; if ($t_key <= count { return date('Y-m-d', strtotime; } else { //查询日期已跨年 $n_days = $days -  - 1 - $search_key); $next_year = $year   1; return $this->getNextWorkDate($next_year . '-01-01', $n_days - 1); } }} $startdate = '2018-09-28';$days = 5; $class = new work_days();$_date_workday = $class->getNextWorkDate;echo $_date_workday;//2018-10-10

 

思路:

参照他事他说加以考察清单列表

1、获取到查询年度内全部职业日数据数组2、获取到查询开始日期在专业日的索引3、总计需询问日期索引4、拿到查询日期

 

以上代码我们能够在地头测验一下,谢谢大家对台本之家的支撑。

1、位运算

依据集结的方法来设置三个月的天天的专门的学问日标识,亦非天天都能够设置的,大家设置事业日标识有关前提,所设置的专业日必需超过当前不久(几近日)的,小于当今日的大家不做设置,只好根据暗许工作日设置(周后生可畏到周一为职业日,星期天和星期天为非专门的学问日)。

正文目录列表:

 

 

测量检验以上存款和储蓄的功效意义,如下图:

 

2、

安装工作日标识的积攒进程,T-SQL代码如下:

澳门新葡萄京娱乐网站 1

澳门新葡萄京娱乐网站 2

 

 

  • 1 = BitOfInt,那么大家就算用贰个int值来保存叁个月持有的职业日标记值(每种专门的学问日标识值:1*power(2,DayOfMonth-1卡塔尔, 整数的位值:1*power(2, BitOfInt卡塔尔(قطر‎,这两个是卓殊的)之和(大家设置变量为WorkDayValueOfMonth),。那样就足以依靠群集的方式来设置三个月的专门的职业日标记。有了职业日标识值之和的int数值,那么什么样分别设置每日的工作日标识值呢?那些将要动用SQL Server提供的按位与运算符,假使(1*power(2,DayOfMonth-1卡塔尔(英语:State of Qatar)卡塔尔国 & WorkDayValueOfMonth 的按位与的结果值为1,那么DayOfMonth所对应的的天则设置为了工作日;借使其结果为0,则设置为了非职业日。

月内日索引和int索引相差1,这几个超级轻便觉察的。

安装日期数据表节日假期日标识

澳门新葡萄京娱乐网站 3

澳门新葡萄京娱乐网站 4

 

我们先不说施工方案,大家先从每月富含的最小运气31以来起。我们再来看SQL Server 提供的数据类型int,那是个有暗号的4字节整数,共计三13个人,第三十个人为标志位,对于非负数该符号位为0,对于负数该符号位为1。非负整数的int独有叁拾一个人来累积数据的;各类月最小运气是31天,那五头确实很巧合吗。假设大家将二个月的每一天赋别对应一个int的每个人,从第一天到最后一天资别对应int的率先位到第叁12人,如以下表格:

  1 IF OBJECT_ID(N'dbo.usp_Calendar_WorkDaySet', 'P') IS NOT NULL
  2 BEGIN
  3     DROP PROCEDURE dbo.usp_Calendar_WorkDaySet;
  4 END
  5 GO
  6  
  7 --==================================
  8 -- 功能: 设置指定月份的工作日标志
  9 -- 说明: 具体实现阐述 
 10 -- 作者: XXX
 11 -- 创建: yyyy-MM-dd
 12 -- 修改: yyyy-MM-dd XXX 修改内容描述
 13 --==================================
 14  
 15 CREATE PROCEDURE usp_Calendar_WorkDaySet
 16 (
 17     @intMonths INT,                                -- 指定的日期月数
 18     @intWorkDayValueSum INT,                    -- 指定的日期月数的所有工作日标志值之和
 19     @bitIsUseDefault BIT = 0,                    -- 是否使用默认设置,1:使用默认设置(周一到周五为工作日,周六和周日非工作日),0:基于指定的日期月数的所有工作日标志值之和来设置
 20  
 21     -- 方便记录用户操作日志
 22     --@chvnUser NVARCHAR(20),                        -- 指定的用户
 23     --@intUserID INT,                                -- 指定的用户ID
 24     --@chvUserIP VARCHAR(40),                        -- 指定的用户IP
 25     --@chvnUserFrom NVARCHAR(30),                    -- 指定的用户位置
 26  
 27     @chvnErrMsg NVARCHAR(100) OUTPUT            -- 错误异常消息字符串
 28 )
 29     --$Encode$--
 30 AS
 31 BEGIN
 32     SET NOCOUNT ON;
 33  
 34     SET @intMonths = dbo.ufn_GetValidDateNum(@intMonths);
 35  
 36     IF @intWorkDayValueSum IS NULL OR @intWorkDayValueSum < 0
 37     BEGIN
 38         SET @intWorkDayValueSum = 0;
 39     END
 40  
 41     SET @chvnErrMsg = N'';
 42  
 43     DECLARE @tintResultValue AS TINYINT;
 44     SET @tintResultValue = 1; -- 默认存在错误
 45  
 46     DECLARE
 47         @dtmNow AS DATETIME,
 48         @intDays AS INT;
 49     SELECT
 50         @dtmNow = GETDATE(),
 51         @intDays = dbo.ufn_Days(@dtmNow);
 52  
 53     IF @intMonths < dbo.ufn_Months(@dtmNow)
 54     BEGIN
 55         SET @chvnErrMsg = N'不能设置小于当前月份的工作日标志。';
 56  
 57         RETURN @tintResultValue;
 58     END
 59  
 60     DECLARE
 61         @WorkDayValueSum AS INT,
 62         @DayCount AS INT;
 63     SELECT
 64         @WorkDayValueSum = 0,
 65         @DayCount = 0;
 66  
 67     SELECT
 68         @WorkDayValueSum = SUM(POWER(2, [DayOfMonth] - 1))
 69         ,@DayCount = COUNT(1)
 70     FROM dbo.Calendar
 71     WHERE Months = @intMonths
 72         AND [Days] >= @intDays   1;
 73  
 74     IF @DayCount = 0 OR @WorkDayValueSum = 0
 75     BEGIN
 76         SET @chvnErrMsg = N'日历数据表不存在满足条件的数据。';
 77  
 78         RETURN @tintResultValue;
 79     END
 80  
 81     IF @intWorkDayValueSum = @WorkDayValueSum
 82     BEGIN
 83         SET @tintResultValue = 0;
 84  
 85         RETURN @tintResultValue;
 86     END
 87  
 88     DECLARE    @intRowCount AS INT;
 89     SELECT @intRowCount = 0;
 90  
 91     BEGIN TRY
 92         IF @bitIsUseDefault = 0
 93         BEGIN
 94             UPDATE Calendar
 95             SET WorkdayFlag = POWER(2, [DayOfMonth] - 1) & @intWorkDayValueSum
 96             WHERE Months = @intMonths 
 97                 AND [Days] >= @intDays   1;
 98         END
 99         ELSE
100         BEGIN
101             UPDATE Calendar
102             SET WorkdayFlag = CASE WHEN dbo.ufn_DayOfWeek(CalendarDate) <= 5 THEN 1 ELSE 0 END
103             WHERE Months = @intMonths 
104                 AND [Days] >= @intDays   1;
105         END
106  
107         SET @intRowCount = @@ROWCOUNT;
108  
109         SET @tintResultValue = 0;
110     END TRY
111     BEGIN CATCH        
112         SET @chvnErrMsg = N'设置指定月的工作日标志发生错误。';
113  
114         RETURN @tintResultValue;
115     END CATCH
116  
117     RETURN @tintResultValue;
118 END
119 GO
120  
121 -- Test Code
122 DECLARE
123     @intMonths AS INT,
124     @intWorkDayValueSum AS INT,
125     @bitIsUseDefault AS BIT,
126     @chvnErrMsg AS NVARCHAR(100),
127     @tintResultVaule AS TINYINT;
128 SELECT
129     @intMonths = 0,                                            -- int
130     @intWorkDayValueSum = 0,                                -- int
131     @bitIsUseDefault = NULL,                                -- bit
132     @chvnErrMsg = N'',                                        -- nvarchar(100)
133     @tintResultVaule = 1;                                    -- tinyint
134  
135 EXEC @tintResultVaule = dbo.usp_Calendar_WorkDaySet
136     @intMonths = @intMonths,                                -- int
137     @intWorkDayValueSum = @intWorkDayValueSum,                -- int
138     @bitIsUseDefault = @bitIsUseDefault,                    -- bit
139     @chvnErrMsg = @chvnErrMsg OUTPUT                        -- nvarchar(100)
140  
141 SELECT @chvnErrMsg AS 'Error Message'
142     ,@tintResultVaule AS 'Return Value';
143 GO
144  
145 -- Test Code
146 -- 2016-02月份
147 -- 根据国家节假日获取的工作日标志值和以及工作日总数
148 SELECT 
149     WorkDayValueSum = SUM(T.WorkDayFlag2 * POWER(2, T.[DayOfMonth] - 1))
150     ,WorkDayCount = SUM(T.WorkDayFlag2 * 1)
151 FROM (
152     SELECT 
153         Months
154         ,[DayOfMonth]
155         ,WorkDayFlag
156         ,WorkDayFlag2 = CASE 
157                             WHEN [DayOfMonth] = 6 THEN 1
158                             WHEN [DayOfMonth]  BETWEEN 7 AND 12 THEN 0
159                             WHEN [DayOfMonth] = 14 THEN 1
160                             ELSE WorkDayFlag END
161     FROM dbo.Calendar
162     WHERE Months = dbo.ufn_Months('2016-02-01')
163 ) AS T
164 GO
165  
166 DECLARE
167     @intMonths AS INT,
168     @intWorkDayValueSum AS INT,
169     @bitIsUseDefault AS BIT,
170     @chvnErrMsg AS NVARCHAR(100),
171     @tintResultVaule AS TINYINT;
172 SELECT
173     @intMonths = dbo.ufn_Months('2016-02-01'),                -- int
174     @intWorkDayValueSum = 333963327,                        -- int
175     @bitIsUseDefault = 0,                                    -- bit
176     @chvnErrMsg = N'',                                        -- nvarchar(100)
177     @tintResultVaule = 1;                                    -- tinyint
178  
179 EXEC @tintResultVaule = dbo.usp_Calendar_WorkDaySet
180     @intMonths = @intMonths,                                -- int
181     @intWorkDayValueSum = @intWorkDayValueSum,                -- int
182     @bitIsUseDefault = @bitIsUseDefault,                    -- bit
183     @chvnErrMsg = @chvnErrMsg OUTPUT                        -- nvarchar(100)
184  
185 SELECT @chvnErrMsg AS 'Error Message'
186     ,@tintResultVaule AS 'Return Value';
187 GO
188  
189  

1、

    本文谈到了SQL Server的按位运算符,着重解说了日历数量表中的专门的职业日标识的安装的管理格局,基于群集的拍卖方法,结合按位与运算符来管理的情势。

 

澳门新葡萄京娱乐网站 5

拿到工作日标识的存放进度,T-SQL代码如下:

澳门新葡萄京娱乐网站 6

3、总结语

总结语

既是有了安装职业日标识的艺术,当然也可能有得到钦赐月的办事日值和和脚上一个月的职业日的数码。依据以上大家提供八个存款和储蓄进程,分别对应设置职业日标记或获得职业日标志的法力。

上篇博文(日历数量表详细明白)中,总括出来二个日历数据表,该表的字段列(WorkDayFlag bit卡塔尔国表示是或不是工作日。暗中认可设置周黄金时代到周五为事业日,周末和星期天为非工作日的。可是国家官方节日一时候会攻下暗许职业日(周风流洒脱到星期一中一天或若干天)的,那就要涉及设置工作日的意义。那么些大家很明朗能想到一条日历数量记录的扩充设置,也是基于迭代或游标的艺术。

 

澳门新葡萄京娱乐网站 7

月内日索引(从1开始计数) int位索引(从0开始计数)
1
0
2
1
3
2
……
……
28
28
29
28
30
29
31
30

 

 1 IF OBJECT_ID(N'dbo.usp_Calendar_WeekDayGet', 'P') IS NOT NULL
 2 BEGIN
 3     DROP PROCEDURE dbo.usp_Calendar_WeekDayGet
 4 END
 5 GO
 6  
 7 --==================================
 8 -- 功能: 获取满足条件的日期月数的工作日值和工作日总数
 9 -- 说明: 具体实现阐述 
10 -- 作者: XXX
11 -- 创建: yyyy-MM-dd
12 -- 修改: yyyy-MM-dd XXX 修改内容描述
13 --==================================
14 CREATE PROCEDURE dbo.usp_Calendar_WeekDayGet
15 (
16     @intStartMonths INT,                -- 指定的开始日期月数
17     @intEndMonths INT                    -- 指定的结束日期月数
18 )
19     --$Encode$--
20 AS 
21 BEGIN
22     SET NOCOUNT ON;
23  
24     SET @intStartMonths = dbo.ufn_GetValidDateNum(@intStartMonths);
25     SET @intEndMonths = dbo.ufn_GetValidDateNum(@intEndMonths);
26  
27     IF @intStartMonths > @intEndMonths
28     BEGIN
29         DECLARE @intTemp AS INT;
30         SET @intTemp = @intStartMonths;
31         SET @intStartMonths = @intEndMonths;
32         SET @intEndMonths = @intTemp;
33     END
34  
35     SELECT
36         Months
37         ,WorkDayValueSum = ISNULL(SUM(WorkDayFlag * POWER(2, [DayOfMonth] - 1)), 0)
38         ,WorkDayCount = ISNULL(SUM(WorkDayFlag * 1), 0)
39     FROM dbo.Calendar
40     WHERE Months BETWEEN @intStartMonths AND @intEndMonths
41     GROUP BY Months;
42 END
43 GO
44  
45 -- Test Code
46 DECLARE
47     @intStartMonths AS INT,
48     @intEndMonths AS INT,
49     @tintResultValue AS TINYINT;
50  
51 SELECT
52     @intStartMonths = dbo.ufn_Months('2015-06-01'),
53     @intEndMonths = dbo.ufn_Months('2016-03-02'),
54     @tintResultValue = 1;    -- 默认范围值
55  
56 EXEC @tintResultValue = dbo.usp_Calendar_WeekDayGet
57     @intStartMonths = @intStartMonths,        -- int
58     @intEndMonths = @intEndMonths;            -- int
59  
60 SELECT @tintResultValue AS 'Return Value (1:Have Error,0:No Error)'
61 GO

测量检验以上存款和储蓄的职能意义,如下图:

 

 

 

4、参谋清单列表

 

询问201501月份的日历数量,如下图:

2、设置日历数量表节日假期日标识

5、

SQL Server支持的按位运算符.aspx)有三个,分别为:按位与(&).aspx)、按位或(|).aspx)、按位异或(^卡塔尔.aspx)。位运算符用于 int、smallint 或 tinyint 数据,如今SQL Server能扶持的按位运算的最大整数类型为Int(4字节整数)。有关上述多个按位运算符的详实使用,请参见微软的SQL Server的联机支持。

既然如此知道了月内日索引( 大家设位变量DayOfMonth卡塔尔国和int位索引(大家设置变量为BitOfInt卡塔尔的关联,两个之间的关联选择变量表示为:DayOfMonth

4、

3、

位运算

 

 

 

据他们说迭代或游标的情势留意思谋实在存在性能难题的,二个月最少有28天,最多的有31天,要是设置三个月底每天的工作日标识字段列值,需求很频仍的数据库连接财富的,即使分享壹回数据库连接,数次推行的也是存在品质难题的。那什么缓和常规格局存在的个性难点吧?

澳门新葡萄京娱乐网站 8

本文由澳门新葡萄京娱乐网站发布于编程知识,转载请注明出处:SQL Server时间粒度系列----第8节位运算以致安装日

关键词: