这是可能的,但仅使用 sql 非常非常难看。但是,如果您可以使用存储函数,那么看起来也很漂亮。
从您在问题中链接的SO问题中,我们知道以下表达式计算两个日期之间的工作日数:
5 * (DATEDIFF(@E, @S) DIV 7) +
MID('0123455501234445012333450122234501101234000123450',
7 * WEEKDAY(@S) + WEEKDAY(@E) + 1, 1)
如果我们将此表达式乘以 9,即每个工作日的工作小时数,我们会得到business hours diff
。添加两个时间戳之间的小时调整可以得到最终的表达式,然后我们可以对其进行平均
45 * (DATEDIFF(@E, @S) DIV 7) +
9 * MID('0123455501234445012333450122234501101234000123450',
7 * WEEKDAY(@S) + WEEKDAY(@E) + 1, 1) +
TIMESTAMPDIFF(HOUR, DATE(@E), @E) -
TIMESTAMPDIFF(HOUR, DATE(@S), @S)
所以,丑陋但有效的查询是:
SELECT
clients.name
, AVG(45 * (DATEDIFF(jobs.time_updated, jobs.time_created) DIV 7) +
9 * MID('0123455501234445012333450122234501101234000123450',
7 * WEEKDAY(jobs.time_created) + WEEKDAY(jobs.time_updated) + 1, 1) +
TIMESTAMPDIFF(HOUR, DATE(jobs.time_updated), jobs.time_updated) -
TIMESTAMPDIFF(HOUR, DATE(jobs.time_created), jobs.time_created)) AS average_response
, AVG(45 * (DATEDIFF(jobs.time_closed, jobs.time_created) DIV 7) +
9 * MID('0123455501234445012333450122234501101234000123450',
7 * WEEKDAY(jobs.time_created) + WEEKDAY(jobs.time_closed) + 1, 1) +
TIMESTAMPDIFF(HOUR, DATE(jobs.time_closed), jobs.time_closed) -
TIMESTAMPDIFF(HOUR, DATE(jobs.time_created), jobs.time_created)) AS average_closure
, COUNT(jobs.id) AS ticket_count
, SUM(time_total) AS time_spent
FROM jobs
LEFT JOIN clients ON jobs.client = clients.id
WHERE jobs.status = 'closed'
GROUP BY jobs.client
更好的选择是创建一个存储函数来处理business hours diff
logic.
DROP FUNCTION IF EXISTS BUSINESSHOURSDIFF;
DELIMITER $$
CREATE FUNCTION BUSINESSHOURSDIFF(start_time TIMESTAMP, end_time TIMESTAMP)
RETURNS INT UNSIGNED
BEGIN
RETURN 45 * (DATEDIFF(end_time, start_time) DIV 7) +
9 * MID('0123455501234445012333450122234501101234000123450',
7 * WEEKDAY(start_time) + WEEKDAY(end_time) + 1, 1) +
TIMESTAMPDIFF(HOUR, DATE(end_time), end_time) -
TIMESTAMPDIFF(HOUR, DATE(start_time), start_time);
END $$
DELIMITER ;
然后根据需要调用它。
SELECT
clients.name
, avg(BUSINESSHOURSDIFF(jobs.time_created, jobs.time_updated)) AS average_response
, avg(BUSINESSHOURSDIFF(jobs.time_created, jobs.time_closed)) AS average_closure
, count(jobs.id) AS ticket_count
, SUM(time_total) AS time_spent
FROM jobs
LEFT JOIN clients ON jobs.client = clients.id
WHERE jobs.status = 'closed'
GROUP BY jobs.client;