我几天前问了一个类似的问题,但我没有找到我正在寻找的答案,特别是SQL(问题是Check if time in a database surpasses specific hour)。
基本上,我有以下问题:
SELECT DAYNAME(arrivalTime) AS day, COUNT(*) AS count
FROM bookings
WHERE HOUR(arrivalTime) = 13
AND DAYNAME(arrivalTime) = 'Monday'
这将计算星期一13:00开始预订的条目数。如何更改此项以便计算从到达时间到接送时间的每个小时?
例如,如果我的到达时间 - pickupTime为13:00 - 17:00 ,那么13:00,14:00,15:00和16:00都将此计为条目。
有一些建议,但没有真正设法与他们相处。
编辑:
我制作的日历:
我的数据库:
样本和预期产出:
arrivalTime - pickupTime
13 - 15 (hours 13, 14 are counted)
10 - 14 (hours 10, 11, 12, 13 are counted)
16 - 17 (hours 16 are counted)
13 - 17 (hours 13, 14, 15, 16 are counted)
11 - 12 (hours 11 are counted)
基本上,现在它只是计算到达时间为X的条目数。因此,如果我们有10个条目从星期一13:00开始,我链接的HTML表格将有13:00旁边的数字10。我想说的是,每小时都在计算当时有多少预订。
为了更容易想象,这只是一个狗窝。我们每小时检查狗窝里有多少只狗。因此,如果从13:00到15:00进行预订,则不应该在时间重叠时将+1添加到13:00,还要添加到14:00。也许比我想象的要复杂一点。
编辑2:
现在我在我的功能
中得到了这个查询SELECT DAYNAME(arrivalTime) AS day, COUNT(*) AS count
FROM bookings
WHERE HOUR(arrivalTime) = $hour
AND DAYNAME(arrivalTime) = '$dayname'
在HTML中我传递像这样的值
<td>
<span>
<p style="float:left">10:00</p>
<p style="float:right"> (<?php $var->get_CalendarCount($conn,10,'Monday'); ?>)</p>
</span>
</td>
答案 0 :(得分:1)
你的意思是这样吗?
SELECT DAYNAME(arrivalTime) AS day, COUNT(arrivalTime) AS count
FROM bookings
WHERE TIME(arrivalTime) BETWEEN '13:00:00' AND '17:00:00'
AND DAYNAME(arrivalTime) = 'Monday'
或者如果你只需要13,14,15,16,17那么:
SELECT DAYNAME(arrivalTime) AS day, COUNT(arrivalTime) AS count
FROM bookings
WHERE (TIME(arrivalTime) BETWEEN '13:00:00' AND '17:00:00')
AND MINUTE(TIME(arrivalTime)) = 0
AND SECOND(TIME(arrivalTime)) = 0
AND DAYNAME(arrivalTime) = 'Monday'
//编辑以回复评论
所以你需要在13:00 - 13.59,14:00 - 14:59等13:00 - 17:00之间计算预订吗?
SELECT DAYNAME(arrivalTime) AS day, COUNT(arrivalTime) AS count, CONCAT(HOUR(arrivalTime), ':00 - ', HOUR(arrivalTime) + 1, ':00') as Hours
FROM bookings
WHERE (HOUR(arrivalTime) BETWEEN '13' AND '17')
AND DAYNAME(arrivalTime) = 'Monday'
GROUP BY HOUR(arrivalTime);
//编辑2
不幸的是我现在没有时间修复我写的查询,但是使用函数而不是单一选择会更容易(每隔一小时选择一次)。
但有两件事:
//编辑3
当您为日历的任何单元格调用此功能时,请检查此功能是否满足您的需要。如果要返回x而不是零,只需输入if并返回char。它应该工作10:00 - 10:59(一小时)或10:00 - 16:59(总时间)
CREATE FUNCTION fn_getCount(p_dayName VARCHAR(10), p_fromHour INT, p_toHour INT)
RETURNS INT
BEGIN
DECLARE v_count INT;
SELECT COUNT(b.arrivalTime) INTO v_count
FROM bookings b
WHERE
((HOUR(b.arrivalTime) BETWEEN p_fromHour AND p_toHour - 1) OR
(HOUR(b.pickupTime) BETWEEN p_fromHour AND p_toHour - 1) OR
(HOUR(b.arrivalTime) < p_fromHour AND HOUR(b.pickupTime) > p_toHour - 1)) AND
DAYNAME(b.arrivalTime) = p_dayName;
RETURN v_count;
END;
这样称呼:
SELECT fn_getCount('Saturday', 14, 17);
我不知道php,我知道.NET,但是如果你想要一个服务器返回的整个表,你可以简单地创建一个存储过程,在需要的地方调用这个函数并从PHP调用该过程。我不是专家,但如果您想要服务器返回整个日历,则必须创建数据透视表
//编辑4(2015年11月30日00:04)
这里有单细胞和存储过程的功能,可以生成整个日历,我已经添加了评估供应日期的第一天的功能,因为你需要提供日期,否则它将返回所有星期一,而不是只有你感兴趣的那一周。
评估单个细胞的功能:
DELIMITER $$
DROP FUNCTION IF EXISTS fn_getCount;
CREATE FUNCTION fn_getCount(p_weekDate DATE, p_dayName VARCHAR(10), p_fromHour INT, p_toHour INT)
RETURNS INT
BEGIN
DECLARE v_count INT;
SELECT COUNT(b.arrivalTime) INTO v_count
FROM bookings b
WHERE
((HOUR(b.arrivalTime) BETWEEN p_fromHour AND p_toHour - 1) OR
(HOUR(b.pickupTime) BETWEEN p_fromHour AND p_toHour - 1) OR
(HOUR(b.arrivalTime) < p_fromHour AND HOUR(b.pickupTime) > p_toHour - 1)) AND
DAYNAME(b.arrivalTime) = p_dayName AND
(DATE(b.arrivalTime) BETWEEN fn_firstDayOfWeek(p_weekDate) AND DATE_ADD(fn_firstDayOfWeek(p_weekDate), INTERVAL 6 DAY));
RETURN v_count;
END$$
DELIMITER ;
返回我们提供日期作为参数的一周的星期一日期的功能。
DELIMITER $$
DROP FUNCTION IF EXISTS fn_firstDayOfWeek;
CREATE FUNCTION fn_firstDayOfWeek(day DATE)
RETURNS DATE
BEGIN
RETURN SUBDATE(day, WEEKDAY(day));
END$$
DELIMITER ;
将整个日历生成为数据透视表的步骤:
DELIMITER $$
DROP PROCEDURE IF EXISTS sp_GetCalendar;
CREATE PROCEDURE sp_GetCalendar(
p_weekDate DATE,
p_fromHour INT,
p_toHour INT
)
BEGIN
DECLARE v_currHour INT;
DROP TEMPORARY TABLE IF EXISTS Calendar;
CREATE TEMPORARY TABLE Calendar
(
Hours VARCHAR(30),
Monday VARCHAR(30),
Tuesday VARCHAR(30),
Wednesday VARCHAR(30),
Thursday VARCHAR(30),
Friday VARCHAR(30),
Saturday VARCHAR(30),
Sunday VARCHAR(30)
);
SET v_currHour = p_fromHour;
START TRANSACTION;
WHILE (v_currHour < p_toHour) DO
INSERT INTO Calendar (Hours, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday)
VALUES (
CONCAT(v_currHour, ':00 - ', v_currHour + 1, ':00'),
CASE WHEN fn_getCount(p_weekDate, 'Monday', v_currHour, v_currHour + 1) = 0 THEN 'x' ELSE fn_getCount(p_weekDate, 'Monday', v_currHour, v_currHour + 1) END,
CASE WHEN fn_getCount(p_weekDate, 'Tuesday', v_currHour, v_currHour + 1) = 0 THEN 'x' ELSE fn_getCount(p_weekDate, 'Tuesday', v_currHour, v_currHour + 1) END,
CASE WHEN fn_getCount(p_weekDate, 'Wednesday', v_currHour, v_currHour + 1) = 0 THEN 'x' ELSE fn_getCount(p_weekDate, 'Wednesday', v_currHour, v_currHour + 1) END,
CASE WHEN fn_getCount(p_weekDate, 'Thursday', v_currHour, v_currHour + 1) = 0 THEN 'x' ELSE fn_getCount(p_weekDate, 'Thursday', v_currHour, v_currHour + 1) END,
CASE WHEN fn_getCount(p_weekDate, 'Friday', v_currHour, v_currHour + 1) = 0 THEN 'x' ELSE fn_getCount(p_weekDate, 'Friday', v_currHour, v_currHour + 1) END,
CASE WHEN fn_getCount(p_weekDate, 'Saturday', v_currHour, v_currHour + 1) = 0 THEN 'x' ELSE fn_getCount(p_weekDate, 'Saturday', v_currHour, v_currHour + 1) END,
CASE WHEN fn_getCount(p_weekDate, 'Sunday', v_currHour, v_currHour + 1) = 0 THEN 'x' ELSE fn_getCount(p_weekDate, 'Sunday', v_currHour, v_currHour + 1) END);
SET v_currHour = v_currHour + 1;
END WHILE;
INSERT INTO Calendar (Hours, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday)
VALUES (
CONCAT('Total: ', p_fromHour, ':00 - ', p_toHour, ':00'),
CASE WHEN fn_getCount(p_weekDate, 'Monday', p_fromHour, p_toHour) = 0 THEN 'x' ELSE fn_getCount(p_weekDate, 'Monday', p_fromHour, p_toHour) END,
CASE WHEN fn_getCount(p_weekDate, 'Tuesday', p_fromHour, p_toHour) = 0 THEN 'x' ELSE fn_getCount(p_weekDate, 'Tuesday', p_fromHour, p_toHour) END,
CASE WHEN fn_getCount(p_weekDate, 'Wednesday', p_fromHour, p_toHour) = 0 THEN 'x' ELSE fn_getCount(p_weekDate, 'Wednesday', p_fromHour, p_toHour) END,
CASE WHEN fn_getCount(p_weekDate, 'Thursday', p_fromHour, p_toHour) = 0 THEN 'x' ELSE fn_getCount(p_weekDate, 'Thursday', p_fromHour, p_toHour) END,
CASE WHEN fn_getCount(p_weekDate, 'Friday', p_fromHour, p_toHour) = 0 THEN 'x' ELSE fn_getCount(p_weekDate, 'Friday', p_fromHour, p_toHour) END,
CASE WHEN fn_getCount(p_weekDate, 'Saturday', p_fromHour, p_toHour) = 0 THEN 'x' ELSE fn_getCount(p_weekDate, 'Saturday', p_fromHour, p_toHour) END,
CASE WHEN fn_getCount(p_weekDate, 'Sunday', p_fromHour, p_toHour) = 0 THEN 'x' ELSE fn_getCount(p_weekDate, 'Sunday', p_fromHour, p_toHour) END);
COMMIT;
SELECT * FROM Calendar;
DROP TEMPORARY TABLE IF EXISTS Calendar;
END$$
DELIMITER ;
请他们进行测试,如下所示:
CALL sp_GetCalendar('2015-11-07', 10, 17);
SELECT fn_getCount('2015-11-07', 'Saturday', 10, 17);
SELECT fn_firstDayOfWeek('2015-11-07');
<强>输出:强>
代码可能有点多余,但我的时间确实很短。
答案 1 :(得分:1)
我想即使在特定时间内没有预订也需要计算。你需要一个小时表才能做到这一点。
SELECT H.day_name AS day,
Count(b.arrivaltime) AS count
FROM hour_table H
LEFT OUTER JOIN bookings B
ON h.day_name = Dayname(arrivaltime)
AND h.hours = Hour(arrivaltime)
WHERE h.hours BETWEEN 13 AND 17
AND h.day_name = 'Monday'
GROUP BY H.day_name
修改:如果您不想计算X
和Y
之间的每次预订。然后你需要条件聚合。像这样的东西
Count(case when h.hours BETWEEN 13 AND 17 then b.arrivaltime .. end) AS count
如果有足够的信息
,可以添加完整的答案