查找不同行中日期时间间隔的重叠?

Posted

技术标签:

【中文标题】查找不同行中日期时间间隔的重叠?【英文标题】:Find the overlap of the datetime interval in different rows? 【发布时间】:2020-08-27 18:51:46 【问题描述】:

我有一张记录一些任务的表格。不同的任务有不同的TaskConfigId。任务的每次运行都有不同的 TaskGuid。所以相同的任务但不同的运行会有不同的TaskGuid。每次运行都将从状态 10 开始,并以状态 20 结束。它可能具有介于 10 到 20 之间的其他状态。

不同的任务正在按计划运行。有些运行非常频繁,有些则不运行。因此,它可以同时运行多个任务,但每个任务一次只能运行一个实例。现在,由于一些未知的原因,有时,一项任务可能有多个实例在运行。我们想查询数据库以查看是否发生了这种情况。

这里是日志的截图,很正常。发生问题时,对于 TaskGuid 不同的 TaskConfigId#100,它可能在 3468118 和 3468117 之间有一行。我们想找到这样的案例。

我认为我们需要通过TaskConfigId和TaskGuid进行分组,然后找到状态20和10(比如A和B)的TaskTrackingId,然后检查相同的TaskConfigId,A和B之间是否有TaskTrackingId。

SELECT TaskConfigId, TaskGuid
    , MAX(CreatedDate) AS [Max]
    , MIN(CreatedDate) AS [Min]
FROM [AptFeed].[TaskTracking]
GROUP BY TaskConfigId, TaskGuid
HAVING MAX(TaskStatusId) = 20 AND MIN(TaskStatusId) = 10
ORDER BY [Max] DESC

这样,我可以找到任务运行的开始和结束日期时间,但是我们怎样才能找到不同的任务运行是否有重叠呢?

在 C# 中很容易做到这一点,但我们可以在 SQL Server 中做到这一点吗?

澄清一个问题:请参阅下面的屏幕截图。对于#270,任务运行“7b433....”有 10 和 20。但是,在它们之间,#270 有 3 个条目。其中“db055....”开始较早,所以我们在屏幕截图上看不到 10。这就是我们要查明的情况。如果中间没有#270的入口,就ok了。并且可以有其他任务的条目,即 260、280、100....

【问题讨论】:

mysql SQLServer?是什么,对我来说看起来更像 SQLServer 请不要发送垃圾邮件标签,这些标签旨在帮助为您的问题收集正确的受众。 只是为了理解,如果另一个运行重叠意味着它将始终具有状态10,具有相同的TaskConfigId,但不同的TaskGuidTaskTrackingId。我说的对吗? 不必是10。只要有条目,就不应该是。我在帖子末尾添加了屏幕截图和解释以澄清这一点。谢谢 【参考方案1】:

了解在您的环境中可能需要考虑更多因素,您可以尝试这样的事情(可在 SSMS 中运行):

/* TASKTRACKING MOCK-UP */
DECLARE @TaskTracking TABLE (
    TaskTrackingId INT,
    TaskConfigId INT,
    TaskGuid VARCHAR(50),
    TaskStatusId INT,
    CreatedDate DATETIME
);

/* TASKTRACKING DATA */
INSERT INTO @TaskTracking ( TaskTrackingId, TaskConfigId, TaskGuid, TaskStatusId, CreatedDate )
VALUES
    ( 3426760, 270, 'e881670a-e643-4b25-a4f4-dd30fc28bd23', 10, '2020-08-26 19:00:00.053' ), 
    ( 3424077, 270, '9ff 91e67-071b-48f2-bOdb-172d3e9f 234a', 20, '2020-08-26 17:19:30.740' ), 
    ( 3422102, 270, '9ff 91e67-071b-4812-bOdb-172d3e9f 234a', 10, '2020-08-26 16:52:36.443' ), 
    ( 3422101, 270, '6ef629ae-8ee1-44b7-aedd-43b246379e8f', 20, '2020-08-26 16:52:36.430' ), 
    ( 3411426, 270, '6ef629ae-8ee1-44b7-aedd-43b246379e8f', 10, '2020-08-26 14:26:01.613' ), 
    ( 3411425, 270, 'ce4f8688-5191-4735-a7e9-525781f3d72f', 20, '2020-08-26 14:26:01.600' ), 
    ( 3400704, 270, 'ce4f8688-5191-4735-a7e9-525781f3d72f', 10, '2020-08-26 12:00:00.190' ), 
    ( 3397311, 270, '7dbcc241-3c86-426f-9f6b-ef 12dfd5b2a1', 20, '2020-08-26 11:12:37.650' ), 
    ( 3397310, 270, '7dbcc241-3c86-426f-9f6b-ef 12dfd5b2a1', 10, '2020-08-26 11:12:37.620' ), 
    ( 3397309, 270, 'e46782caf 763-4580-89f 9-99da0d6a1762', 20, '2020-08-26 11:12:37.610' ), 
    ( 3397077, 270, 'e46782caf763-4580-89f9-99da0d6a1762', 10, '2020-08-26 11:09:47.410' ), 
    ( 3397076, 270, '7b433f62-6089-44ba-ad6c-eb767bd7e056', 20, '2020-08-26 11:09:47.400' ), 
    ( 3397075, 270, '1890732e-cec3-476-9f44-69d37105ee40', 20, '2020-08-26 11:09:47.400' ), 
    ( 3395100, 270, '1890732e-cec3-476-9f44-69d37105ee40', 10, '2020-08-26 10:42:42.740' ), 
    ( 3395099, 270, 'db05513a-20d5-4e40-96cc-c310ff1a0d4b', 20, '2020-08-26 10:42:42.730' ),
    ( 3394726, 270, '7b433f62-6089-44ba-ad6c-eb767bd7e056', 10, '2020-08-26 10:37:46.750' );

/* Return a list of tasks that have overlapping TaskConfigId values */
SELECT
    *
FROM (
    SELECT
        TaskConfigId,
        TaskGuid, 
        MIN ( CreatedDate ) AS MinDate,
        MAX ( CreatedDate ) AS MaxDate
    FROM @TaskTracking AS task
    GROUP BY
        TaskConfigId, TaskGuid
) AS Tasks
OUTER APPLY (

    SELECT 
        COUNT ( DISTINCT TaskGuid ) AS OverlapTasks,
        STRING_AGG ( TaskGuid, '|' ) AS OverlapGuids
    FROM @TaskTracking AS x
    WHERE
        x.TaskConfigId = Tasks.TaskConfigId
        AND x.CreatedDate > Tasks.MinDate AND x.CreatedDate <= Tasks.MaxDate
        AND x.TaskGuid <> Tasks.TaskGuid

) AS Overlaps
WHERE
    Overlaps.OverlapTasks > 0
ORDER BY
    MinDate;

返回

+--------------+--------------------------------------+-------------------------+-------------------------+--------------+--------------------------------------------------------------------------------------------------------------+
| TaskConfigId |               TaskGuid               |         MinDate         |         MaxDate         | OverlapTasks |                                                 OverlapGuids                                                 |
+--------------+--------------------------------------+-------------------------+-------------------------+--------------+--------------------------------------------------------------------------------------------------------------+
|          270 | 7b433f62-6089-44ba-ad6c-eb767bd7e056 | 2020-08-26 10:37:46.750 | 2020-08-26 11:09:47.400 |            2 | 1890732e-cec3-476-9f44-69d37105ee40|1890732e-cec3-476-9f44-69d37105ee40|db05513a-20d5-4e40-96cc-c310ff1a0d4b |
|          270 | 1890732e-cec3-476-9f44-69d37105ee40  | 2020-08-26 10:42:42.740 | 2020-08-26 11:09:47.400 |            1 | 7b433f62-6089-44ba-ad6c-eb767bd7e056                                                                         |
+--------------+--------------------------------------+-------------------------+-------------------------+--------------+--------------------------------------------------------------------------------------------------------------+

【讨论】:

以上是关于查找不同行中日期时间间隔的重叠?的主要内容,如果未能解决你的问题,请参考以下文章

如何根据关键和时间间隔有效地查找父记录?

如何使用开始和结束日期时间在司机的行程中查找重叠记录

防止日期间隔重叠并与 Oracle +11g 中的触发器保持一致

使用 Linq C# 在 DataTable 中查找重叠的日期

Impala SQL:合并具有重叠日期的行。不支持 WHERE EXISTS 和递归 CTE

从两组日期范围 C# 中查找间隔日期范围