T-SQL合并非重叠时间

时间:2014-09-17 10:33:57

标签: sql merge overlap

使用SQL 2008 R2并坚持下去。

我有几组时间范围,我需要合并与resource1上的作业没有重叠的范围。在我的示例数据中,我希望来自ResourceID 1的所有作业和来自所有其他资源的作业与资源1上的EXISTING作业不重叠(即想象我试图从其他资源中选择候选来填充ResourceID 1连续工作)

以下是一些示例数据,我的失败尝试和预期结果。我设法排除了除了工作10之外应该排除的所有内容

-- Need to select all other jobs from all other resources that can be merged into resource 1 where there is no overlap with existing jobs in resource 1 only


CREATE TABLE #Jobs
    (
     resourceID INT
    ,JobNo INT
    ,StartTime SMALLDATETIME
    ,EndTime SMALLDATETIME
    ,ShouldBeOmitted BIT
    )

 INSERT INTO [#Jobs]
        SELECT
            1
           ,1
           ,'2014-08-01 08:00:00'
           ,'2014-08-01 10:00:00'
           ,0
        UNION
        SELECT
            1
           ,2
           ,'2014-08-01 18:00:00'
           ,'2014-08-01 20:00:00'
           ,0
        UNION
        SELECT
            2
           ,3
           ,'2014-08-01 07:00:00'
           ,'2014-08-01 20:00:00' -- should be omitted as ends in middle of job 1
           ,1
        UNION
        SELECT
            2
           ,4
           ,'2014-08-01 09:00:00'
           ,'2014-08-01 11:00:00' -- should be omitted as starts in middle of job 1
           ,1
        UNION
        SELECT
            2
           ,5
           ,'2014-08-01 10:00:00'
           ,'2014-08-01 11:00:00' -- OK because it starts exactly at end of job 1
           ,0
        UNION
        SELECT
            2
           ,6
           ,'2014-08-01 12:00:00'
           ,'2014-08-01 14:00:00' -- OK because no overlap
           ,0
        UNION
        SELECT
            2
           ,7
           ,'2014-08-01 16:00:00'
           ,'2014-08-01 18:00:00' -- OK because it ends exactly at start of job 2
           ,0
        UNION
        SELECT
            2
           ,8
           ,'2014-08-01 19:00:00'
           ,'2014-08-01 19:30:00' -- should be omitted as it is inside tme range of job 2
           ,1
        UNION
        SELECT
            2
           ,9
           ,'2014-08-01 20:00:00'
           ,'2014-08-01 21:00:00'  -- should be OK as it is starts exactly at end of job 2
           ,0
        UNION
        SELECT
            4
           ,10
           ,'2014-08-01 02:00:00'
           ,'2014-08-01 22:00:00'  -- should be omitted as spans other jobs
           ,1
        UNION
        SELECT
            5
           ,11
           ,'2014-08-01 08:00:00'
           ,'2014-08-01 10:00:00'  -- should be omitted as it matches other job
           ,1


 SELECT
    'Source Data', *
 FROM
    #Jobs 


 SELECT
    'ExpectedResults'
   ,*
 FROM
    [#Jobs] j
 WHERE
    j.[ShouldBeOmitted] = 0

 SELECT
    'MyResults'
   ,[j].[ResourceID]
   ,[j].[JobNo]
   ,[j].[StartTime]
   ,[j].[EndTime]
   ,[j].[ShouldBeOmitted]
 FROM
    #Jobs j
 WHERE
    [ResourceID] = 1
 UNION ALL
 SELECT
    'MyResults'
   ,[j2].[ResourceID]
   ,[j2].[JobNo]
   ,[j2].[StartTime]
   ,[j2].[EndTime]
   ,[j2].[ShouldBeOmitted]
 FROM
    #Jobs j2
 WHERE
    [ResourceID] != 1
    AND NOT EXISTS ( SELECT
                        1
                     FROM
                        #Jobs
                     WHERE
                        [ResourceID] = 1
                        AND (
                             (
                              -- Starts within existing job
                              j2.[StartTime] >= [StartTime]
                              AND j2.[StartTime] < [EndTime]
                             )
                             OR (
                                 -- Ends withing existing job
                                 j2.[EndTime] > [StartTime]
                                 AND j2.[EndTime] <= [EndTime]
                                )
                            ) )
 ORDER BY
    [j].[resourceID]
   ,j.starttime

非常感谢任何帮助

由于

标记

1 个答案:

答案 0 :(得分:0)

我不太确定我了解您实际需要的数据。根据您的解释,我认为您需要来自Jobs的所有Resource 1和来自Jobs的{​​{1}} Resource 2来自Jobs的{​​{1}}。这是我的解决方案:

Resource 2

此SQL返回:

SELECT 
    * 
FROM 
    #Jobs AS x1 
WHERE 
    (x1.resourceID = 1) OR 
    NOT EXISTS (SELECT 1 FROM #Jobs AS y INNER JOIN #Jobs z ON 
        (y.resourceID = 2) AND (z.resourceID = 1) AND 
        ((y.StartTime BETWEEN z.StartTime AND z.EndTime) OR (y.EndTime BETWEEN z.StartTime AND z.EndTime) )
        WHERE ((y.resourceID = x1.resourceID) AND (y.JobNo = x1.JobNo)));

实际上在您的示例中存在错误 - 您指出正确的元素是来自资源2的作业5,但它由作业1资源1覆盖。

如果我不太清楚,请发表评论。

编辑: 这是您需要的查询(基于时间差1分钟)

resourceID  JobNo   StartTime   EndTime
1   1   2014-08-01 08:00:00 2014-08-01 10:00:00
1   2   2014-08-01 18:00:00 2014-08-01 20:00:00
2   3   2014-08-01 07:00:00 2014-08-09 20:00:00
2   6   2014-08-01 12:00:00 2014-08-01 14:00:00
2   7   2014-08-01 16:00:00 2014-08-09 18:00:00