使用 SQL 选择重叠的日期时间事件

发布于 2024-09-28 06:18:52 字数 714 浏览 3 评论 0原文

我有一个 SQL 表 Events(ID int、Event int、StartTime datetime、Duration int)。

Event 是事件代码(1=系统运行,2=中断)

Duration 是事件处于活动状态的秒数。

我想要获取事件 1 处于活动状态的秒数,但减去事件 2 的持续时间。

例如,事件 1 为 1:00 至 6:00,事件 2 为 0:00 至 2:00,事件 2 为 5:00 至 6:00。总时间应为2:00至5:00-> 3小时。

我能想到一个办法:对于每个事件1找到所有可以与事件1相交的事件2,对于每个事件2在该集中:修剪其持续时间以仅获取在事件 1 期间处于活动状态的部分。

例如,对于我的事件 1 (1:00 - 6:00),我将找到事件 2 (0:00 - 2:00),只获取我感兴趣的部分(1:00-2:00);找到另一个活动2(5:00-6:00),找到我感兴趣的部分(这是整个活动5:00-6:00) - 总共是两个小时。活动1总时间为5小时; 5 小时 - 2 小时(活动 2)为 3 小时。

但如果在指定的时间范围内有数千个事件,这将不起作用,所以我更喜欢没有循环(游标)的解决方案提示。

I have a SQL table Events (ID int, Event int, StartTime datetime, Duration int).

Event is event code (1=system running, 2=break)

Duration is the amount of seconds that the event was active.

I'd like to get the amount of seconds that event 1 was active, but subtract the duration of event 2.

E.g. event 1 was from 1:00 to 6:00, event 2 from 0:00 to 2:00 and event 2 from 5:00 to 6:00. The total time should be from 2:00 to 5:00 -> 3 hours.

There is a way I can think of: for each event 1 find all events 2 that can intersect with event 1, and for each event 2 in that set: trim its duration to get only the part that was active during its event 1.

e.g. for my event 1 (1:00 - 6:00) I'll find event 2 (0:00 - 2:00), get only the part that interests me (1:00-2:00); find another event 2(5:00-6:00), get the part that interests me (it's whole event 5:00-6:00) - that summed up are two hours. The total time of event 1 was 5 hours; 5 hrs - 2 hrs (event 2) is 3 hours.

But this won't work if there are thousands of events in the specified time frame, so I'd prefer a hint of solution without loops (cursors).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

笑脸一如从前 2024-10-05 06:18:52
;WITH CTE AS (
    SELECT 
        evnt2.id as ID, 
        sum(evnt1.duration) as Duration 
    from 
        #events evnt1
        INNER JOIN #events evnt2
            ON evnt1.id <> evnt2.id
    WHERE 
        DATEADD(second, evnt1.duration, evnt1.starttime)
        BETWEEN 
            evnt2.starttime AND DATEADD(second, evnt2.duration, evnt2.starttime)
    GROUP BY evnt2.id
) 
SELECT 
    #events.duration - CTE.duration, 
    * 
FROM 
    #events 
    INNER JOIN CTE 
        ON #events.id = CTE.id
;WITH CTE AS (
    SELECT 
        evnt2.id as ID, 
        sum(evnt1.duration) as Duration 
    from 
        #events evnt1
        INNER JOIN #events evnt2
            ON evnt1.id <> evnt2.id
    WHERE 
        DATEADD(second, evnt1.duration, evnt1.starttime)
        BETWEEN 
            evnt2.starttime AND DATEADD(second, evnt2.duration, evnt2.starttime)
    GROUP BY evnt2.id
) 
SELECT 
    #events.duration - CTE.duration, 
    * 
FROM 
    #events 
    INNER JOIN CTE 
        ON #events.id = CTE.id
清音悠歌 2024-10-05 06:18:52

我能想到的最简单的方法是使用多个自连接。我说多个是因为事件 2 可以在事件 1 之前或期间开始。

如果事件 2 始终在事件 1 之前开始,这里有一些代码可以回答您的问题。

select DateDiff(s,e1.StartTime, DateAdd(s,e2Before.Duration,e2Before.StartTime)) 
from events e1
join events e2Before
    on (e1.StartTime between e2Before.StartTime and DateAdd(s,e2Before.duration,e2Before.StartTime))
    and e1.event = 1
    and e2Before.event = 2

要完全回答这个问题,您需要添加另一个连接,其中包含一些DateAdd 参数稍微交换了一下,以满足事件 2 在事件 1 开始后开始的情况。

The simplest way I can think of to do this is with multiple self-joins. I say multiple because the Event 2 can start before or during Event 1.

Here's a bit of code that will answer your question if Event 2 always starts before Event 1.

select DateDiff(s,e1.StartTime, DateAdd(s,e2Before.Duration,e2Before.StartTime)) 
from events e1
join events e2Before
    on (e1.StartTime between e2Before.StartTime and DateAdd(s,e2Before.duration,e2Before.StartTime))
    and e1.event = 1
    and e2Before.event = 2

To answer the question fully, you'll need to add another join with some of the DateAdd parameters swapped around a bit to cater for situations where Event 2 starts after Event 1 starts.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文