SQL方法创建
-- 查询时间段内的工作时间函数(剔除周末与非工作时间)
-- 参数解释
-- _st: 开始时间
-- _ed: 结束时间
-- _hour1: 工作时间开始小时
-- _hour2: 工作时间结束小时
-- _minute1: 工作时间开始分钟
-- _minute2: 工作时间结束分钟
-- 返回工作时间总分钟数
DELIMITER $$
CREATE FUNCTION `work_minute_sum`(_st DATETIME, _ed DATETIME, _hour1 INT, _hour2 INT, _minute1 INT, _minute2 INT) RETURNS int(11)
BEGIN
-- 每周有10080分钟
DECLARE _one_week_minute INT DEFAULT 10080;
-- 每天全勤工作分钟数
DECLARE _one_day_work_minute INT DEFAULT (_hour2 - _hour1) * 60 - _minute1 + _minute2;
-- 查询周期开始时间小时值
DECLARE _st_hour INT DEFAULT DATE_FORMAT(_st, '%H');
-- 查询周期结束时间小时值
DECLARE _ed_hour INT DEFAULT DATE_FORMAT(_ed, '%H');
-- 查询周期开始时间分钟值
DECLARE _st_minute INT DEFAULT DATE_FORMAT(_st, '%i');
-- 查询周期结束时间分钟值
DECLARE _ed_minute INT DEFAULT DATE_FORMAT(_ed, '%i');
-- 查询周期开始时间在周几
DECLARE _st_week INT DEFAULT DATE_FORMAT(_st, '%w');
-- 查询周期结束时间在周几
DECLARE _ed_week INT DEFAULT DATE_FORMAT(_ed, '%w');
-- 查询周期总分钟数
DECLARE _diffminute INT;
-- 交换位置使用日期临时变量
DECLARE _che DATETIME;
-- 正负值标志
DECLARE _flag INT DEFAULT 1;
-- 周值临时变量
DECLARE _week INT;
-- 小时差值临时变量
DECLARE _hour_div INT;
-- 周差值临时变量
DECLARE _count_week INT DEFAULT 0;
-- 工作分钟数结果值变量
DECLARE _work_minute INT DEFAULT 0;
-- 每日工作开始时间大于结束时间,异常工作定义数据,直接返回工作0分钟
IF ((_hour1 > _hour2) || (_hour1 = _hour2 && _minute1 >= _minute2)) THEN
RETURN 0;
END IF;
-- 查询周期开始时间大于结束时间,交换两个时间变量值,并记录负值标记
IF _st > _ed THEN
SET _che = _st;
SET _st = _ed;
SET _ed = _che;
SET _flag = -1;
END IF;
-- 查询周期总分钟数值
SET _diffminute = TIMESTAMPDIFF(MINUTE, _st, _ed);
-- 查询周期跨越总周数(向下取整)
SET _count_week = FLOOR(_diffminute / _one_week_minute);
-- 工作时长初始总周数相应的工作时长
SET _work_minute = _count_week * 5 * _one_day_work_minute;
-- 查询周期开始时间增加总周数*7天
SET _st = DATE_ADD(_st, INTERVAL (_count_week * 7) DAY);
-- 以开始日期与结束日期均工作满一天计算,减去多计算的部分即可
-- 将查询周期开始时间小时、分钟值设置为工作日开始时间,再减去多计算的分钟数
IF (_st_week = 0 || _st_week = 6) THEN
SET _work_minute = _work_minute;
ELSEIF ((_st_hour > _hour2) || (_st_hour = _hour2 && _st_minute >= _minute2)) THEN
SET _work_minute = _work_minute - _one_day_work_minute;
ELSEIF (_st_hour > _hour1) || (_st_hour = _hour1 && _st_minute > _minute1) THEN
SET _hour_div = _st_hour - _hour1;
SET _work_minute = _work_minute - (_hour_div * 60) - (_st_minute - _minute1);
END IF;
-- 将查询周期结束时间小时、分钟值设置为工作日结束时间,再减去多计算的分钟数
IF (_ed_week = 0 || _ed_week = 6) THEN
SET _work_minute = _work_minute;
ELSEIF (_ed_hour < _hour1) || (_ed_hour = _hour1 && _ed_minute < _minute1) THEN
SET _work_minute = _work_minute - _one_day_work_minute;
ELSEIF (_ed_hour < _hour2) || (_ed_hour = _hour2 && _ed_minute < _minute2) THEN
SET _hour_div = _hour2 - _ed_hour;
SET _work_minute = _work_minute - (_hour_div * 60) - (_minute2 - _ed_minute);
END IF;
-- 按天循环,计算最后一周的工作时长
loop_cal:LOOP
SET _week = DATE_FORMAT(_st, '%w');
IF _week != 0 && _week != 6 THEN
SET _work_minute = _work_minute + _one_day_work_minute;
END IF;
IF DATE_FORMAT(_st, '%Y-%m-%d') >= DATE_FORMAT(_ed, '%Y-%m-%d') THEN
LEAVE loop_cal;
END IF;
SET _st = DATE_ADD(_st, INTERVAL 1 DAY);
END LOOP;
RETURN _work_minute * _flag;
END $$
DELIMITER ;
调用方法
#例:某公司工作时间为上午: 09:00 ~ 12:00,下午: 13:30 ~ 18:00,则在2019年3月3日0点到2019年3月13日22点的总工作时间是:
select work_minute_sum(‘2019-03-03 00:00:00’, ‘2019-03-13 22:00:00’, 9, 12, 0, 0) + work_minute_sum(‘2019-03-03 00:00:00’, ‘2019-03-13 22:00:00’, 13, 18, 30, 0);