提出的问题是计算每行返回的时间(“响应时间”)在2个时间戳(“StartDateTime”和“EndDateTime”)之间,不包括周末。不考虑工作时间或假期。
本案例中的周末定义为周六00:00:00至周日23:59:59。
为这个问题提出解决方案时遇到了困难,所以我想分享我的最终产品。在网上找到了很多解决方案,但大多数都使用了我无法在此应用程序中使用的日历表,或者有一个我不理解的逻辑。解决方案分享如下请随时根据问题提供自己的解决方案,或更正我在代码中看到的任何错误。的问候,
编辑:根据@JuanCarlosOropeza解决方案提供的评论,我提出的并不是最优的。为他提供样本数据以转发不同的解决方案。如果有人有改进,也可以随意参加。
CREATE TABLE SourceTable
(`id` int, `StartDateTime` datetime, `EndDateTime` datetime)
;
INSERT INTO SourceTable
(`id`, `StartDateTime`, `EndDateTime`)
VALUES
(1, '2016-09-20 12:52:00', '2016-09-23 13:15:00'),
(2, '2016-09-19 19:15:00', '2016-09-22 19:15:00'),
(3, '2016-09-01 10:35:00', '2016-09-06 13:15:00'),
(4, '2016-09-26 10:34:00', '2016-09-29 11:25:00'),
(5, '2016-09-01 13:01:00', '2016-09-06 14:55:00'),
(6, '2016-09-05 02:21:00', '2016-09-08 19:15:00'),
(7, '2016-09-27 14:14:00', '2016-10-01 19:15:00'),
(8, '2016-09-27 04:18:00', '2016-09-30 14:15:00'),
(9, '2016-09-01 14:50:00', '2016-09-06 17:25:00'),
(10, '2016-09-20 12:52:00', '2016-09-23 13:15:00'),
(11, '2016-09-26 02:14:00', '2016-09-29 10:15:00'),
(12, '2016-09-01 12:04:00', '2016-09-06 17:05:00'),
(13, '2016-09-20 15:30:00', '2016-09-23 15:15:00'),
(14, '2016-09-02 16:04:00', '2016-09-07 20:55:00'),
(15, '2016-09-23 10:41:00', '2016-09-28 13:05:00'),
(16, '2016-09-27 16:28:00', '2016-10-01 13:15:00'),
(17, '2016-09-27 15:33:00', '2016-10-01 22:45:00'),
(18, '2016-09-20 12:53:00', '2016-09-23 13:25:00'),
(19, '2016-09-19 13:49:00', '2016-09-22 13:05:00'),
(20, '2016-09-20 13:46:00', '2016-09-23 13:15:00'),
(21, '2016-09-01 16:32:00', '2016-09-06 18:05:00'),
(22, '2016-09-01 10:35:00', '2016-09-06 22:45:00'),
(23, '2016-09-26 12:40:00', '2016-09-29 12:35:00'),
(24, '2016-09-27 10:37:00', '2016-09-30 21:25:00'),
(25, '2016-09-27 09:41:00', '2016-09-30 15:15:00'),
(26, '2016-09-16 02:09:00', '2016-09-21 10:05:00'),
(27, '2016-09-20 15:13:00', '2016-09-23 15:15:00'),
(28, '2016-09-20 15:30:00', '2016-09-23 15:15:00'),
(29, '2016-09-27 09:55:00', '2016-09-30 13:25:00'),
(30, '2016-09-27 04:18:00', '2016-09-30 14:15:00')
;
答案 0 :(得分:0)
我考虑到以下逻辑假设创建了这个解决方案。
StartDateTime总是在EndDateTime之前发生(虽然有一些没有,但它正确地计算了时差)
周StartDateTime发生:WEEK(StartDateTime,1)
周EndDateTime发生:WEEK(EndDateTime,1)
周末开始StartDateTime:ADDDATE(TIMESTAMP(DATE(StartDateTime),'00:00:00'),5-WEEKDAY(StartDateTime))
第一个周末后的工作周开始:ADDDATE(TIMESTAMP(DATE(StartDateTime),'00:00:00'),7-WEEKDAY(StartDateTime))
完整查询:
SELECT
id,
StartDateTime,
EndDateTime,
CASE
WHEN ( WEEK(EndDateTime,1) = WEEK(StartDateTime,1) )
THEN
CASE
WHEN ( StartDateTime >= ADDDATE(TIMESTAMP(DATE(StartDateTime),'00:00:00'),5-WEEKDAY(StartDateTime)) )
THEN SEC_TO_TIME(0)
ELSE
CASE
WHEN ( EndDateTime >= ADDDATE(TIMESTAMP(DATE(StartDateTime),'00:00:00'),5-WEEKDAY(StartDateTime)) )
THEN ( TIMEDIFF(ADDDATE(TIMESTAMP(DATE(StartDateTime),'00:00:00'),5-WEEKDAY(StartDateTime)),StartDateTime) )
ELSE ( TIMEDIFF(EndDateTime,StartDateTime) )
END
END
ELSE
CASE
WHEN ( StartDateTime >= ADDDATE(TIMESTAMP(DATE(StartDateTime),'00:00:00'),5-WEEKDAY(StartDateTime)) )
THEN
CASE
WHEN ( EndDateTime >= ADDDATE(ADDDATE(TIMESTAMP(DATE(StartDateTime),'00:00:00'),5-WEEKDAY(StartDateTime)),(WEEK(EndDateTime,1) - WEEK(StartDateTime,1)) * 7) )
THEN ( SEC_TO_TIME(120*3600*(WEEK(EndDateTime,1) - WEEK(StartDateTime,1))) )
ELSE ( SEC_TO_TIME(120*3600*(WEEK(EndDateTime,1) - WEEK(StartDateTime,1) - 1) + TIME_TO_SEC(TIMEDIFF(EndDateTime, ADDDATE(ADDDATE(TIMESTAMP(DATE(StartDateTime),'00:00:00'),7-WEEKDAY(StartDateTime)),7*(WEEK(EndDateTime,1) - WEEK(StartDateTime,1) - 1))))) )
END
ELSE
CASE
WHEN ( EndDateTime >= ADDDATE(ADDDATE(TIMESTAMP(DATE(StartDateTime),'00:00:00'),5-WEEKDAY(StartDateTime)),(WEEK(EndDateTime,1) - WEEK(StartDateTime,1)) * 7) )
THEN ( SEC_TO_TIME(120*(WEEK(EndDateTime,1) - WEEK(StartDateTime,1)) + TIME_TO_SEC(TIMEDIFF(ADDDATE(TIMESTAMP(DATE(StartDateTime),'00:00:00'),5-WEEKDAY(StartDateTime)),StartDateTime))) )
ELSE ( SEC_TO_TIME(TIME_TO_SEC(TIMEDIFF(EndDateTime, ADDDATE(ADDDATE(TIMESTAMP(DATE(StartDateTime),'00:00:00'),7-WEEKDAY(StartDateTime)),7*(WEEK(EndDateTime,1) - WEEK(StartDateTime,1) - 1)))) + TIME_TO_SEC(TIMEDIFF(ADDDATE(TIMESTAMP(DATE(StartDateTime),'00:00:00'),5-WEEKDAY(StartDateTime)),StartDateTime))) )
END
END
END as ResponseTime
FROM
SourceTable;
第一个CASE检查两个时间戳是否在同一周发生。第二层检查StartDateTime是否在第一个周末发生。第三层检查EndDateTime是否在周末发生。根据这些考虑因素输出正确的计算结果。