在预订系统中,我想计算从8am到4pm的两个日期(2019年1月1日至2019年1月2日)之间预订资源的小时总数。
如果预订持续不超过一天,我设法计算出预订资源的总小时数。如果预订持续超过一天,就会出现问题。
通过以下预订,我希望结果是9.5小时。
startDatetime endDatetime
2019-01-01 14:30:00 2019-01-02 18:30:00
这是我尝试过的代码:
SELECT resourceID,
SEC_TO_TIME(sum(LEAST(TIME_TO_SEC(TIME(endDatetime)), TIME_TO_SEC('16:00')) - GREATEST(TIME_TO_SEC(TIME(startDatetime)), TIME_TO_SEC('08:00')))) AS totalTimeBooked
FROM booking
WHERE startDatetime BETWEEN '2019-01-01 00:00:00' AND '2019-01-02 23:59:59'
AND (TIME(startDatetime) BETWEEN '08:00' AND '16:00'
OR TIME(endDatetime) BETWEEN '08:00' AND '16:00')
group by resourceID
答案 0 :(得分:0)
您可以使用以下解决方案为每个booked_time
获取resourceID
:
SELECT
resourceID,
SEC_TO_TIME(
SUM(
CASE WHEN DATEDIFF(DATE(endDatetime), DATE(startDatetime)) = 0 THEN
GREATEST(TIME_TO_SEC(TIMEDIFF(LEAST('16:00:00', TIME(endDatetime)), LEAST(GREATEST('08:00:00', TIME(startDatetime)), '16:00:00'))), 0)
ELSE
TIME_TO_SEC(TIMEDIFF('16:00:00', LEAST(GREATEST('08:00:00', TIME(startDatetime)), '16:00:00')))
+ TIME_TO_SEC(TIMEDIFF(GREATEST('08:00:00', LEAST('16:00:00', TIME(endDatetime))), '08:00:00'))
+ ((DATEDIFF(DATE(endDatetime), DATE(startDatetime)) - 1) * TIME_TO_SEC(TIMEDIFF('16:00:00', '08:00:00')))
END
)
) AS booked_time
FROM table_name
GROUP BY resourceID
您可以使用以下查询来获取每一行的结果(可用于测试上述查询):
SELECT
resourceID, startDatetime, endDatetime,
SEC_TO_TIME(
CASE WHEN DATEDIFF(DATE(endDatetime), DATE(startDatetime)) = 0 THEN
GREATEST(TIME_TO_SEC(TIMEDIFF(LEAST('16:00:00', TIME(endDatetime)), LEAST(GREATEST('08:00:00', TIME(startDatetime)), '16:00:00'))), 0)
ELSE
TIME_TO_SEC(TIMEDIFF('16:00:00', LEAST(GREATEST('08:00:00', TIME(startDatetime)), '16:00:00')))
+ TIME_TO_SEC(TIMEDIFF(GREATEST('08:00:00', LEAST('16:00:00', TIME(endDatetime))), '08:00:00'))
+ ((DATEDIFF(DATE(endDatetime), DATE(startDatetime)) - 1) * TIME_TO_SEC(TIMEDIFF('16:00:00', '08:00:00')))
END
) AS booked_time
FROM table_name
ORDER BY resourceID, startDatetime, endDatetime
注意:您必须小心使用SEC_TO_TIME
功能。在大量数据或大日期范围内,您可以达到TIME
数据类型的最大值:
MySQL检索并以“
TIME
”格式(或“HH:MM:SS
”格式表示小时值)显示HHH:MM:SS
值。TIME
值的范围可以从“-838:59:59
”到“838:59:59
”。小时部分可能是如此之大,因为TIME
类型不仅可以用来表示一天中的某个时间(必须少于24小时),而且可以用来表示经过的时间或两个事件之间的时间间隔(可能大于24小时,甚至是负数)。
来源: https://dev.mysql.com/doc/refman/8.0/en/time.html
您还询问了如何获得入住率。您可以通过上面的查询使用以下解决方案:
SELECT
resourceID,
booked_time,
CONCAT((TIME_TO_SEC(booked_time) / TIME_TO_SEC(TIMEDIFF('16:00:00', '08:00:00')) * 100), '%') AS 'occupancy_rate'
FROM (
SELECT
resourceID,
SEC_TO_TIME(
SUM(
CASE WHEN DATEDIFF(DATE(endDatetime), DATE(startDatetime)) = 0 THEN
GREATEST(TIME_TO_SEC(TIMEDIFF(LEAST('16:00:00', TIME(endDatetime)), LEAST(GREATEST('08:00:00', TIME(startDatetime)), '16:00:00'))), 0)
ELSE
TIME_TO_SEC(TIMEDIFF('16:00:00', LEAST(GREATEST('08:00:00', TIME(startDatetime)), '16:00:00')))
+ TIME_TO_SEC(TIMEDIFF(GREATEST('08:00:00', LEAST('16:00:00', TIME(endDatetime))), '08:00:00'))
+ ((DATEDIFF(DATE(endDatetime), DATE(startDatetime)) - 1) * TIME_TO_SEC(TIMEDIFF('16:00:00', '08:00:00')))
END
)
) AS booked_time
FROM table_name
GROUP BY resourceID
) t_occupancy_rate