【问题标题】:SQL query to find a subseries of non overlapping intervals within a series of overlapping (time) intervalsSQL查询在一系列重叠(时间)间隔内查找非重叠间隔的子序列
【发布时间】:2014-10-30 19:54:56
【问题描述】:

我有一系列可能重叠的编号时间间隔。重要提示:没有两个区间同时开始,开始区间的时间严格递增

插图:

Task 1:  1111111
Task 2:     22222222222    
Task 3:             333333333333333
Task 4:                 444444
Task 5:                         5555555
Task 6:                                  66
   .
   .
   .
        0 --- time axis --->

间隔代表应该执行的任务。我正在寻找一个 SQL 查询,它可以选择可以执行的任务,考虑到只有 一个任务 可以同时执行的约束.第一个任务总是被执行。接下来,从第一个任务完成后开始的所有任务中,执行最早开始的任务。以此类推。

结果:可以执行任务 1、3 和 6。插图:

Task 1:  1111111                             (yes, first)
Task 2:     -----------                      (no, task 1 is running when 2 begins)
Task 3:             333333333333333          (yes)
Task 4:                 ------               (no, task 3 is running when 4 begins)
Task 5:                         -------      (no, task 3 is running when 5 begins)
Task 6:                                  66  (yes)
   .
   .
   .
        0 --- time axis --->

使用迭代,算法很简单:在一个循环中按升序迭代间隔,记住最后选择的间隔的结尾。但是,我想请您提供一个 SQL 查询,可能使用窗口函数,例如可以执行。在 Google BigQuery 上。

任务表的架构:

task_id: integer,
start_timestamp: integer,
duration_seconds: integer.

样本数据:

task_id,start_timestamp,duration_seconds 
1,1,7
2,4,11
3,12,15
4,16,6
5,24,7
6,33,2
7,37,4
8,42,13
9,47,3
10,50,2
11,54,21
12,58,14
13,66,8
14,72,7
15,80,6
16,88,16
17,92,14
18,102,3
19,109,2
20,119,10
21,123,13
22,128,21
23,138,7
24,141,17
25,146,9
26,154,17
27,160,17
28,164,13
29,173,21
30,181,7

结果 - 选定的任务:

1,3,6,7,8,12,14,15,16,19,20,23,25,27,30

样本数据说明:

任务一:1111111 任务二:22222222222 任务三:333333333333333 任务 4:444444 任务五:5555555 任务 6:66 任务 7:7777 任务八:8888888888888 任务 9:999 任务 10:10 任务 11:11xxxxxxxxxxxxxxxxxxxxx 任务 12:12xxxxxxxxxxxx 任务 13:13xxxxxx 任务 14:14xxxx 任务 15:15xxxx 任务 16:16xxxxxxxxxxxxxxx 任务 17:17xxxxxxxxxxxx 任务 18:18 倍 任务 19:19 任务 20:20xxxxxxxx 任务 21:21xxxxxxxxxxxx 任务 22:22xxxxxxxxxxxxxxxxxx 任务 23:23xxxx 任务 24:24xxxxxxxxxxxxxxx 任务 25:25xxxxxxx 任务 26:26xxxxxxxxxxxxxxx 任务 27:27xxxxxxxxxxxxxxx 任务 28:28xxxxxxxxxxx 任务 29:29xxxxxxxxxxxxxxxxxxxxx 任务 30:30xxxx

非常感谢您的帮助。

【问题讨论】:

  • 您能否提供您必须使用的 SQL 架构?你有开始日期时间和持续时间吗?或者您是在使用数字开始索引和 n 位长字符串来指示任务持续时间?
  • Select ... where NOT EXISTS(时间范围重叠的任务)
  • @PatrickM 我有开始时间戳和持续时间。我刚刚将架构附加到问题的文本中。
  • @DariusX。你考虑任务的顺序了吗?例如,任务 3 被选中执行,尽管它与任务 2 和任务 4 有重叠。
  • 请分享示例数据集,否则我将不得不创建一个来尝试此操作。分享更有效率。

标签: sql algorithm google-bigquery intervals date-range


【解决方案1】:

一种方法如下: 找到重叠的任务(开始时间在其他任务的开始时间和结束时间之间),然后提取所有其他任务。

Select task_id
FROM [table]
where Task_id not in(    
    Select B.task_id FROM
    (SELECT task_id, start_timestamp, duration_seconds ,start_timestamp+duration_seconds as end_timestamp
    FROM [table] ) as A
    CROSS JOIN EACH
    (SELECT task_id, start_timestamp, duration_seconds ,start_timestamp+duration_seconds as end_timestamp
    FROM [table] ) as B
    where B.start_timestamp>=A.start_timestamp
    and B.start_timestamp<A.end_timestamp
    and A.task_id<>b.task_id)

此解决方案未使用窗口函数。

使用窗口函数是可行的,但您必须假设并发并行作业的限制(在本例中为 3)。这里我使用 LAG 窗口函数来查找 3 个前置任务并检查某个任务是否与其中一个重叠(开始时间在上一个开始任务的开始时间和结束时间之间)

Select task_id
FROM
(Select task_id, start_timestamp, duration_seconds ,end_timestamp
,LAG(task_id,1) OVER (ORDER BY start_timestamp) as LAG_task_id_1
,LAG(start_timestamp,1) OVER (ORDER BY start_timestamp) as LAG_start_timestamp_1
,LAG(duration_seconds,1) OVER (ORDER BY start_timestamp) as LAG_duration_seconds_1
,LAG(end_timestamp,1) OVER (ORDER BY start_timestamp) as LAG_end_timestamp_1
,LAG(task_id,2) OVER (ORDER BY start_timestamp) as LAG_task_id_2
,LAG(start_timestamp,2) OVER (ORDER BY start_timestamp) as LAG_start_timestamp_2
,LAG(duration_seconds,21) OVER (ORDER BY start_timestamp) as LAG_duration_seconds_2
,LAG(end_timestamp,2) OVER (ORDER BY start_timestamp) as LAG_end_timestamp_2
,LAG(task_id,3) OVER (ORDER BY start_timestamp) as LAG_task_id_3
,LAG(start_timestamp,3) OVER (ORDER BY start_timestamp) as LAG_start_timestamp_3
,LAG(duration_seconds,3) OVER (ORDER BY start_timestamp) as LAG_duration_seconds_3
,LAG(end_timestamp,3) OVER (ORDER BY start_timestamp) as LAG_end_timestamp_3
FROM
(SELECT task_id, start_timestamp, duration_seconds ,start_timestamp+duration_seconds as end_timestamp
FROM [table] ))
where 
(NOT(start_timestamp>=LAG_start_timestamp_1 and start_timestamp<LAG_end_timestamp_1)
and NOT(start_timestamp>=LAG_start_timestamp_2 and start_timestamp<LAG_end_timestamp_2)
and NOT(start_timestamp>=LAG_start_timestamp_3 and start_timestamp<LAG_end_timestamp_3))
OR LAG_start_timestamp_1 IS NULL

希望这会有所帮助...

【讨论】:

  • 感谢您的回答。如果我理解得很好,它会发现不重叠的任务。但是,它不能以所需的方式处理任务的顺序。例如 task 3task 2 重叠,但它仍然是结果集的一部分。原因是,task 2 不是结果集的一部分(task 1task 2 开始时正在运行),因此在决定时无关紧要任务 3 是否可以执行。我知道这个问题的难度。如果存在 SQL 解决方案,则必须以某种方式对已接受任务的阻塞行为进行建模。
  • 如果有并发任务限制,可以尝试使用LAG功能,加入验证之前任务有效性的条件。
【解决方案2】:

刚刚写了一些非常相关的东西(在oracle中),也许它可以帮助某人。 我在http://technology.amis.nl/2007/05/07/creating-a-gantt-chart-in-sql/找到了我的解决方案

这里有一段代码有助于说明甘特图。

WITH 
PERIODS AS
  ( SELECT  TASK_ID LABEL  ,      
            START_TIMESTAMP START_DATE  ,      
            START_TIMESTAMP+DURATION_SECONDS END_DATE  
    FROM   testet
  ), 
LIMITS AS -- determine the earliest starting date and the latest end date to determine the overall width of the chart
  ( SELECT  MIN(START_DATE) PERIOD_START  ,      
            MAX(END_DATE) PERIOD_END  ,      
            80 WIDTH -- set the width as the number of characters  
    FROM   PERIODS
  ), 
BARS AS
  ( SELECT   LPAD(LABEL, '20')||'|' ACTIVITY  ,        
            (START_DATE - PERIOD_START)/(PERIOD_END - PERIOD_START) * WIDTH FROM_POS, -- the starting position for the bar          
            (END_DATE - PERIOD_START)/(PERIOD_END - PERIOD_START)   * WIDTH TO_POS   -- the end position for the bar  
    FROM     PERIODS  ,        LIMITS
  ) 
SELECT  ACTIVITY||        
        LPAD('I',FROM_POS)         ||
        RPAD('-', TO_POS - FROM_POS, '-')         ||
        'I' GANTT
FROM     BARS
UNION ALL
SELECT RPAD('_',WIDTH + 22,'_')
FROM   LIMITS
UNION ALL
SELECT  LPAD('|',21)       ||
        PERIOD_START       ||
        LPAD(PERIOD_END, 
        WIDTH - 11)
FROM   LIMITS;

输出:

                   1|--I
                   2|I----I
                   3|   I------I
                   4|     I--I
                   5|        I--I
                   6|            II
                   7|             I-I
                   8|               I-----I
                   9|                  I-I
                  10|                   II
                  11|                    I--------I
                  12|                      I-----I
                  13|                         I---I
                  14|                            I--I
                  15|                               I--I
                  16|                                   I------I
                  17|                                    I-----I
                  18|                                        I-I
                  19|                                           II
                  20|                                               I----I
                  21|                                                 I-----I
                  22|                                                   I--------I
                  23|                                                       I--I
                  24|                                                         I-------I
                  25|                                                           I---I
                  26|                                                              I-------I
                  27|                                                                I-------I
                  28|                                                                  I-----I
                  29|                                                                      I--------I
                  30|                                                                         I--I
______________________________________________________________________________________________________
                    |1                                                                  194

【讨论】:

    猜你喜欢
    • 2023-01-10
    • 1970-01-01
    • 2013-01-07
    • 2016-12-17
    • 2017-06-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-14
    相关资源
    最近更新 更多