如何编写随行的当前迭代而变化的自连接条件

时间:2019-05-15 20:15:21

标签: mysql sql

表(测试)具有说明

+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| task  | varchar(2)  | NO   |     | NULL    |       |
| time  | int(11)     | NO   |     | NULL    |       |
| type  | char(1)     | NO   |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+

并包含数据

+------+------+------+
| task | time | type |
+------+------+------+
| T1   |    1 | S    |
| T2   |    2 | S    |
| T1   |    7 | E    |
| T1   |    8 | S    |
| T1   |   14 | E    |
| T2   |   15 | E    |
| T1   |   16 | S    |
| T2   |   17 | S    |
| T3   |   20 | S    |
| T1   |   21 | E    |
| T3   |   25 | E    |
+------+------+------+

表示以某个时间单位开始(S)或完成(E)的任务的数据集。是否可以通过输出带有任务开始时间和结束时间的表的方式将其加入。此处(T2,17,S)在最终输出中被跳过,因为尚无结束时间的数据。

最终结果:-

+------+------+------+
| task | start| end  |
+------+------+------+
| T1   |    1 | 7    |
| T2   |    2 | 15   |
| T1   |    8 | 14   |
| T1   |   16 | 21   |
| T3   |   20 | 25   |
+------+------+------+

从最终结果中可以看出,任务T(T1)的所有时间范围都是互斥的[(1,7),(8,15),(16,25)]。

无法弄清楚加入的条件规则

select S_table.task, S_table.time as start, E_table.time as end
from (select * from test where type='S') as S_table
left join (select * from test where type='E') as E_table
on
S_table.task = E_table.task
and
E_table.time should be greater than previous E_table.time for same task
and
E_table.time should be least within S_table.time < E_table.time
  • 在第一行的结果表中,所有E_table.time(7,15,14,21,25)均大于S_table.time(当前行被查看,即1),但是7是因此选择的至少一个

  • 在第二行的结果表中,所有E_table.time都大于上一个(7),即(15,14,21,25)大于2,但至少选择了一个,即15。

1 个答案:

答案 0 :(得分:0)

对于每个开始时间,您需要获取类型'E'的最短时间大于该开始时间:

select t.* from (
  select 
    t.task,
    t.time start,
    (select min(time) from test where type = 'E' and task = t.task and time > t.time) end
  from test t 
  where t.type = 'S' 
) t
where t.end is not null

请参见demo
结果:

| task | start | end |
| ---- | ----- | --- |
| T1   | 1     | 7   |
| T2   | 2     | 15  |
| T1   | 8     | 14  |
| T1   | 16    | 21  |
| T3   | 20    | 25  |

通过内部自连接,您可以获得与代码相同的结果:

select S_table.task, S_table.time as start, E_table.time as end
from (select * from test where type='S') as S_table
inner join (select * from test where type='E') as E_table
on
S_table.task = E_table.task
and 
E_table.time = (
  select min(time) from test where type = 'E' and task = S_table.task and time > S_table.time
)
order by S_table.time