获取24小时时间范围内的记录

时间:2019-07-17 14:34:44

标签: mysql

我尝试根据小时数和持续时间在我的表中查找价格。 例如,这是我的桌子

+----+-----------------+------------+----------+---------+
| id | subscription_id | start_time | end_time | pricing |
+----+-----------------+------------+----------+---------+
|  1 |               1 | 22:00:00   | 21:59:59 |     1.5 |
|  2 |               2 | 05:30:00   | 16:29:00 |    0.75 |
|  3 |               2 | 16:30:00   | 18:59:59 |    0.50 |
|  4 |               2 | 19:00:00   | 05:29:59 |     1.5 |
+----+-----------------+------------+----------+---------+

现在,我要查找开始于16:00:00并结束于20:00:00的第二次订阅 我尝试过类似的尝试,但没有成功

SET @startTime := '17:30:00';
SET @endTime := '20:30:00';

SELECT *
FROM subscription_detail_pricing sdp
WHERE (
    (start_time < end_time AND TIME(@startTime) BETWEEN start_time AND end_time)
    OR
    (start_time > end_time AND TIME(@startTime) NOT BETWEEN end_time AND start_time)
    OR
    (start_time < end_time AND TIME(@endTime) BETWEEN start_time AND end_time) 
    OR
    (start_time > end_time AND TIME(@endTime) NOT BETWEEN end_time AND start_time)
) AND subscription_id = 2;

我找不到用于获取与该范围相对应的3条记录的查询方法

如果有人可以提供一些建议,那我就失去了自我-_-

感谢您的阅读 BenWa

2 个答案:

答案 0 :(得分:1)

这看起来像是经典的范围重叠查询。

如果可能的话,您可能会头疼,将包裹"00:00:00"的所有范围分成两行,并使end_time独占

+----+-----------------+------------+----------+---------+
| id | subscription_id | start_time | end_time | pricing |
+----+-----------------+------------+----------+---------+
|  1 |               1 | 00:00:00   | 24:00:00 |     1.5 |
|  2 |               2 | 00:00:00   | 05:30:00 |     1.5 |
|  3 |               2 | 05:30:00   | 16:30:00 |    0.75 |
|  4 |               2 | 16:30:00   | 19:00:00 |    0.50 |
|  5 |               2 | 19:00:00   | 24:00:00 |     1.5 |
+----+-----------------+------------+----------+---------+

然后您的查询变得简单得多

SELECT *

  FROM subscription_detail_pricing

 WHERE start_time < "20:00:00"
   AND end_time > "16:00:00"

注意,由于您要比较的内容,我更喜欢此查询的互斥比较<>

  • start_time < "20:00:00"-将start_time(包括)与输入范围"20:00:00"(不包括)的末尾进行比较
  • end_time > "16:00:00"-将end_time(包括)与输入范围"16:00:00"(包括)的开始进行比较

只要所比较的值中的至少一个是互斥的,  检查<=>=是否相等对我来说没有意义

答案 1 :(得分:1)

要检查时间范围是否重叠,请以Dim foundAt As CodeStringLocation foundAt.StartLine = 10 Do While module.Find("test", foundAt.StartLine, foundAt.StartColumn, ... s为定义范围的开始和结束,并以eb作为开始和终止的时间通常要比较的范围

t

足以检查重叠。但这仅适用于 b <= e AND t > s b<t。在所示的方案中,“ wrap”出现了皱纹,行id = 4,s<e(开始时间)之前是e(结束时间)。


解决此问题的一种方法是仅存储s小于start_time的行。

我们可以通过将end_time行分成两行来实现

id=4

类似地,可以将行+----+-----------------+------------+----------+---------+ | id | subscription_id | start_time | end_time | pricing | +----+-----------------+------------+----------+---------+ | 4 | 2 | 19:00:00 | 24:00:00 | 1.5 | | 5 | 2 | 00:00:00 | 05:30:00 | 1.5 | +----+-----------------+------------+----------+---------+ 指定为

id=1

或者,如果出于某些原因我们需要22:00:00作为开始,我们可以将其分为两个范围

|  1 |               1 | 00:00:00   | 24:00:00 |     1.5 |

采用这种方法:

| 1a  |              1 | 22:00:00   | 24:00:00 |     1.5 |
| 1b  |              1 | 00:00:00   | 22:00:00 |     1.5 |

返回:

SET @bt := '16:00:00' ;
SET @tt := '20:00:00' ;

SELECT sdp.id
     , sdp.start_time
     , sdp.end_time
     , sdp.pricing
     , ( TIME(@bt) <= sdp.end_time AND TIME(@tt) > sdp.start_time ) AS overlap
  FROM sdp
 WHERE sdp.subscription_id = 2

后退/换行范围重叠

如果必须处理向后范围重叠,且end_time在start_time之前,则似乎可以否定用于向前检查的相同条件,并添加范围是向前还是向后的检查。 / p>

  id  start_time  end_time   pricing  overlap  
----  ----------  ---------  -------  -------
   2  05:30:00.0  16:30:00.0    0.75        1
   3  16:30:00.0  19:00:00.0    0.50        1
   4  19:00:00.0  24:00:00.0    1.50        1
   5  00:00:00.0  05:30:00.0    1.50        0

具有原始显示的行(将end_time稍微调整为该范围之外的第一秒)...

SELECT sdp.id
     , sdp.start_time
     , sdp.end_time
     , sdp.pricing
     ,     (sdp.start_time < sdp.end_time AND ( TIME(@bt) <= sdp.end_time AND TIME(@tt) > sdp.start_time )) AS f_overlap
     , NOT (sdp.start_time < sdp.end_time AND ( TIME(@bt) <= sdp.end_time AND TIME(@tt) > sdp.start_time )) AS b_overlap
  FROM sdp
 WHERE sdp.subscription_id = 2 

我们要测试的条件包含在SELECT列表中,这使我们可以更好地了解正在发生的情况。我们还可以在同一行中返回@bt和@tt。

一旦对这些条件进行了测试,我们就可以将它们向下翻转到 id start_time end_time pricing f_overlap b_overlap ---- ---------- ---------- ------- --------- --------- 2 05:30:00.0 16:30:00.0 0.75 1 0 3 16:30:00.0 19:00:00.0 0.50 1 0 4 19:00:00.0 05:30:00.0 1.50 0 1 子句中。

我们需要WHERE这两个条件,因为如果任一条件为真,我们就会重叠。

OR

注意:这些条件尚未经过充分测试。请注意,这些条件要求SELECT sdp.id , sdp.start_time , sdp.end_time , sdp.pricing FROM sdp WHERE sdp.subscription_id = 2 AND ( (sdp.start_time < sdp.end_time AND ( TIME(@bt) <= sdp.end_time AND TIME(@tt) > sdp.start_time )) OR NOT (sdp.start_time < sdp.end_time AND ( TIME(@bt) <= sdp.end_time AND TIME(@tt) > sdp.start_time )) ) 必须在@bt之前。如果我们要为它们处理“后退换行”,则需要进行其他条件检查和条件否定来处理。我们还希望确保使用@bt为00:00和@et在24:00或之后测试范围。


进行设置:

@et

为避免换行,请在start_time之后将所有范围end_time设为

CREATE TABLE sdp (id INT, subscription_id INT, start_time TIME(1), end_time TIME(1), pricing DECIMAL(8,2), PRIMARY KEY (id))
;
INSERT INTO sdp (id, subscription_id, start_time, end_time, pricing) VALUES 
 ( 1 , 1 , '22:00:00'   , '22:00:00' ,  1.50 )
,( 2 , 2 , '05:30:00'   , '16:30:00' ,  0.75 )
,( 3 , 2 , '16:30:00'   , '19:00:00' ,  0.50 )
,( 4 , 2 , '19:00:00'   , '05:30:00' ,  1.50 )
;