计算时间间隔

时间:2015-11-29 15:39:27

标签: mysql sql

我几天前问了一个类似的问题,但我没有找到我正在寻找的答案,特别是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">&nbsp;&nbsp;&nbsp;(<?php $var->get_CalendarCount($conn,10,'Monday'); ?>)</p>
    </span>
</td>

2 个答案:

答案 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);

table

//编辑2

不幸的是我现在没有时间修复我写的查询,但是使用函数而不是单一选择会更容易(每隔一小时选择一次)。

但有两件事:

  1. 如果您想要从ex:10:00-17:00(例如:10:00-10:59)每小时一次,那么所有记录都是在10:00到10:59之间的pickupTime或者到达时间。
  2. 如果你想要从10月到17点这个时期的总和,它不会是一个总和,因为会有重复,例如:10:00-10:59可能包含相同的记录11:00 - 11:59。
  3. //编辑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');
    

    <强>输出:

    enter image description here

    代码可能有点多余,但我的时间确实很短。

答案 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

修改:如果您不想计算XY之间的每次预订。然后你需要条件聚合。像这样的东西

Count(case when h.hours BETWEEN 13 AND 17 then b.arrivaltime .. end) AS count 

如果有足够的信息

,可以添加完整的答案