我尝试根据小时数和持续时间在我的表中查找价格。 例如,这是我的桌子
+----+-----------------+------------+----------+---------+
| 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
答案 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
为定义范围的开始和结束,并以e
和b
作为开始和终止的时间通常要比较的范围
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 )
;