Sql 根据特定时间范围过滤数据的查询
我试图弄清楚如何在T-SQL中编写一个查询,以便根据时间范围过滤出数据。以下是下图所示的数据。每行都是一个会话,每个会话都有一个日期/时间范围。我想排除在凌晨2点到凌晨4点之间发生的任何数据。这是我写的查询,但问题是,如果结束日期持续超过1天,然后超过凌晨2点到4点的时间范围,它仍然会包含数据。第一个亮点是一个很好的例子。突出显示的项目应排除在外 这是我写的问题。运行查询时,第一行仍然没有被排除,这应该是。有办法解决这个问题吗Sql 根据特定时间范围过滤数据的查询,sql,sql-server,tsql,Sql,Sql Server,Tsql,我试图弄清楚如何在T-SQL中编写一个查询,以便根据时间范围过滤出数据。以下是下图所示的数据。每行都是一个会话,每个会话都有一个日期/时间范围。我想排除在凌晨2点到凌晨4点之间发生的任何数据。这是我写的查询,但问题是,如果结束日期持续超过1天,然后超过凌晨2点到4点的时间范围,它仍然会包含数据。第一个亮点是一个很好的例子。突出显示的项目应排除在外 这是我写的问题。运行查询时,第一行仍然没有被排除,这应该是。有办法解决这个问题吗 SELECT * FROM TABLE WHERE CAST(Sta
SELECT *
FROM TABLE
WHERE CAST(StartDate as TIME) NOT BETWEEN '2 am' AND '4 am'
AND
CAST(EndDate as TIME) NOT BETWEEN '2 am' AND '4 am'
AND
DATEDIFF(HH,StartDate, EndDate) < 24
预期结果
City Country StartDate EndDate
Atlanta US 8/22/2020 23:00 8/23/2020 1:30
Dallas US 8/22/2020 10:30 8/22/2020 17:30
Miami US 8/22/2020 5:30 8/22/2020 12:00
Los Angeles US 8/23/2020 14:00 8/24/2020 1:20
Miami US 8/21/2020 15:30 8/21/2020 23:30
Seattle US 8/22/2020 4:30 8/22/2020 23:30
只有最后一个会被过滤掉。您的条件相当于:
WHERE CAST(StartDate as TIME) NOT BETWEEN '2:00:00' AND '4:00:00' AND
CAST(EndDate as TIME) NOT BETWEEN '2:00:00' AND '4:00:00' AND
DATEDIFF(hour, StartDate, EndDate) < 24
都在24小时之内。对于前两个,开始时间显然不在范围内。停止时间为4:30:00,比排除时间框架少30分钟
最后一个看起来会被逻辑过滤掉
编辑:
如果您不希望重叠,那么我建议:
WHERE ( (CAST(StartDate as TIME) >= '04:00:00' AND
(CAST(EndDate as TIME) > CAST(StartDate as TIME) OR
CAST(EndDate as TIME) < '02:00:00'
)
) OR
(CAST(StartDate as TIME) < '02:00:00' AND
CAST(EndDate as TIME) < '02:00:00'
)
) AND
EndDate < DATEADD(day, 1, StartDate)
仅当跨度超过一天时,才需要最后一个条件
NOT BETWEEN '2:00:00' AND '4:00:00' AND
CAST(EndDate as TIME) NOT BETWEEN '2:00:00' AND '4:00:00' AND
DATEDIFF(hour, StartDate, EndDate) < 24
好吧,这可能不是最简单的解决方案,但它是有效的 基本上,这个查询查找StartDate之后的下一个相关凌晨2点,因此如果StartDate在凌晨4点之后,那么它是第二天凌晨2点,如果它在凌晨2点之前,那么它是今天。如果相关的凌晨2点在结束日期之后,则行是OK的,它不会与窗口重叠。如果不是在之后,那么我们有一个重叠 为了计算这一差异,我们必须计算出凌晨2点是今天还是明天,因此加1天 当StartDate或EndDate在窗口内时,您现有的逻辑工作
declare @Test table (City varchar(24), Country varchar(12), StartDate datetime, EndDate datetime);
insert into @Test (City, Country, StartDate, EndDate)
values
('Atlanta','US','8/22/2020 23:30','8/23/2020 4:30'),
('Atlanta','US','8/22/2020 23:00','8/23/2020 1:30'),
('Dallas','US','8/22/2020 10:30','8/22/2020 17:30'),
('Miami','US','8/22/2020 5:30','8/22/2020 12:00'),
('Los Angeles','US','8/23/2020 14:00','8/24/2020 1:20'),
('New York','US','8/25/2020 1:00','8/25/2020 4:30'),
('New York','US','8/22/2020 1:30','8/22/2020 2:30'),
('Miami','US','8/21/2020 15:30','8/21/2020 23:30'),
('Seattle','US','8/22/2020 4:30','8/22/2020 23:30'),
('Seattle','US','8/26/2020 3:30','8/26/2020 4:30');
select *
from @Test
where cast(StartDate as time) not between '2 am' and '4 am'
and cast(EndDate as time) not between '2 am' and '4 am'
and dateadd(day, case when cast(StartDate as time) > '04:00:00' then 1 else 0 end, dateadd(hh, 2, convert(datetime,convert(date, StartDate)))) >= EndDate;
注释:我还没有测试边缘情况,例如,EDATEDATE正好是2AM,或者StestDead正好是4AM——我把它留给您。
请考虑将您的数据作为DDL/DML语句发布,或者至少作为格式化文本,这样我们就可以复制和粘贴它。Hi @ DaleK,我把数据添加为格式化文本。谢谢如果您添加您的预期结果,这将有助于澄清排除在凌晨2点到凌晨4点之间发生的任何数据。这是否意味着您要将第一行8/22 23:30到8/24 04:30拆分为8/22 23:30到8/23 02:00、8/23 04:00到8/24 02:00和8/24 04:00到8/24 04:30的行?抱歉@DaleK,第一个突出显示的行的结束日期是8/23。不是8/24。我已经更新了数据集。您好@HABO,我将添加预期结果。我只想排除在该时间范围内发生的任何数据,或者不考虑日期的任何数据。例如对于第一行,开始日期开始于8/22/20 23:30,但结束于8/23/20 04:30。因此,作为时间范围,它发生在该时间范围内,因此应排除在外。这有意义吗?@Dee。不,我不清楚。但其他人似乎很清楚。如果开始日期在凌晨2点之后但在凌晨4点之前,会发生什么情况?@Dee你原来的情况可以处理这个问题。我的改进只处理了你原来的状况不符合的情况。declare @Test table (City varchar(24), Country varchar(12), StartDate datetime, EndDate datetime);
insert into @Test (City, Country, StartDate, EndDate)
values
('Atlanta','US','8/22/2020 23:30','8/23/2020 4:30'),
('Atlanta','US','8/22/2020 23:00','8/23/2020 1:30'),
('Dallas','US','8/22/2020 10:30','8/22/2020 17:30'),
('Miami','US','8/22/2020 5:30','8/22/2020 12:00'),
('Los Angeles','US','8/23/2020 14:00','8/24/2020 1:20'),
('New York','US','8/25/2020 1:00','8/25/2020 4:30'),
('New York','US','8/22/2020 1:30','8/22/2020 2:30'),
('Miami','US','8/21/2020 15:30','8/21/2020 23:30'),
('Seattle','US','8/22/2020 4:30','8/22/2020 23:30'),
('Seattle','US','8/26/2020 3:30','8/26/2020 4:30');
select *
from @Test
where cast(StartDate as time) not between '2 am' and '4 am'
and cast(EndDate as time) not between '2 am' and '4 am'
and dateadd(day, case when cast(StartDate as time) > '04:00:00' then 1 else 0 end, dateadd(hh, 2, convert(datetime,convert(date, StartDate)))) >= EndDate;