Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 根据特定时间范围过滤数据的查询_Sql_Sql Server_Tsql - Fatal编程技术网

Sql 根据特定时间范围过滤数据的查询

Sql 根据特定时间范围过滤数据的查询,sql,sql-server,tsql,Sql,Sql Server,Tsql,我试图弄清楚如何在T-SQL中编写一个查询,以便根据时间范围过滤出数据。以下是下图所示的数据。每行都是一个会话,每个会话都有一个日期/时间范围。我想排除在凌晨2点到凌晨4点之间发生的任何数据。这是我写的查询,但问题是,如果结束日期持续超过1天,然后超过凌晨2点到4点的时间范围,它仍然会包含数据。第一个亮点是一个很好的例子。突出显示的项目应排除在外 这是我写的问题。运行查询时,第一行仍然没有被排除,这应该是。有办法解决这个问题吗 SELECT * FROM TABLE WHERE CAST(Sta

我试图弄清楚如何在T-SQL中编写一个查询,以便根据时间范围过滤出数据。以下是下图所示的数据。每行都是一个会话,每个会话都有一个日期/时间范围。我想排除在凌晨2点到凌晨4点之间发生的任何数据。这是我写的查询,但问题是,如果结束日期持续超过1天,然后超过凌晨2点到4点的时间范围,它仍然会包含数据。第一个亮点是一个很好的例子。突出显示的项目应排除在外

这是我写的问题。运行查询时,第一行仍然没有被排除,这应该是。有办法解决这个问题吗

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;