Mysql 如何计算表的连续范围

Mysql 如何计算表的连续范围,mysql,sql,Mysql,Sql,我有如下表格: VideoId StartTime EndTime EntityMid 1001 1 2 a 1001 2 3 a 1001 7 8 b 1001 10 11 a 1001 11 12 a 1002 4 5 c

我有如下表格:

VideoId    StartTime EndTime EntityMid
1001         1         2        a
1001         2         3        a
1001         7         8        b
1001         10        11       a
1001         11        12       a
1002         4         5        c
1002         7         8        c
我希望得到以下结果:

VideoId    EntityMid duration
1001        a         2
1001        b         1
1001        a         2
1002        c         1
1002        c         1
我尝试了窗口函数和自连接,但似乎不起作用。非常感谢你的帮助

我的错误sql代码:

挑选* 从…起 选择* 由StartTime作为lead_EntityId通过videoId命令进行的LeadEntityId超额分配, 提前期通过videoId超额支付,以StartTime作为提前期 从 B 其中EntityId=lead\u EntityId 和结束时间+1=提前期\结束时间
我相信您可以做得更好,并优化这一组子查询,但目前我所做的是:

创建的表和插入的值:

create table myTable (VideoId int, StartTime int, EndTime int, EntityMid char);

insert into myTable values (1001, 1, 2,  'a');
insert into myTable values (1001, 2, 3,  'a');
insert into myTable values (1001, 3, 4,  'a');
insert into myTable values (1001, 7, 8,  'b');
insert into myTable values (1001, 10, 11,'a');
insert into myTable values (1001, 11, 12,'a');
insert into myTable values (1002, 4, 5,  'c');
insert into myTable values (1002, 7, 8,  'c');
以及查询:

select VideoId
       , EntityMid
       , Durationes
from
(
select VideoId
       , EntityMid
       , sum(Durationes) Durationes
       , seq_nbr
from (
select VideoId
       , EntityMid
       , Durationes
       , sum(new_grp) OVER ( PARTITION BY  VideoId ORDER BY VideoId, StartTime) AS seq_nbr 
from
(
select VideoId
       , EntityMid
       , (EndTime - StartTime ) as Durationes
       , StartTime
       , CASE
            WHEN  grouped = LAG (grouped) OVER ( PARTITION BY  VideoId  ORDER BY VideoId, StartTime, EntityMid)
                THEN  0
                ELSE  1
        END AS new_grp  
from 
(
select VideoId
       , EntityMid
       , StartTime
       , EndTime
       , count('1')
       , case 
            when ((LEAD(StartTime, 1) OVER (ORDER BY StartTime))-StartTime) = 1 and VideoId = (LEAD(VideoId, 1) OVER (ORDER BY VideoId))  then 1
            when (StartTime - (LAG(StartTime, 1) OVER (ORDER BY StartTime))) = 1 and VideoId = (LAG(VideoId, 1) OVER (ORDER BY VideoId))  then 1
         end grouped
from myTable 
group by VideoId
         , StartTime
         , EndTime
         , EntityMid
order by VideoId
         , StartTime
         ,EndTime
         , EntityMid
) a
) b
) c
group by VideoId
       , EntityMid
       , seq_nbr
) d;

小提琴:这是一种缺口和孤岛问题

对于特定的数据,可以使用“左联接”来确定孤岛是否开始。然后使用累积总和和聚合:

select t.videoid, t.EntityMid,
       max(t.EndTime) - min(t.StartTime) as duration
from (select t.*,
             sum(case when tprev.EntityMid is null then 1 else 0 end) over
                 (partition by t.videoid order by t.StartTime) as grp
      from t left join
           t tprev
           on t.videoid = tprev.videoid and
              t.EntityMid = tprev.EntityMid and
              t.StartTime = tprev.EndTime
     ) t
group by t.videoid, t.EntityMid, grp;

是一个dbfiddle

为什么末尾有两个EntityId为'c'的记录?我本以为那个岛会被报道为一个单一的记录。您可以包括您迄今为止尝试过的SQL吗?@TimBiegeleisen这两个c行没有StartTimen+1=EndTimen我们希望您到目前为止尝试了一些解决问题的方法,请向我们展示您的努力。@TimBiegeleisen因为Starttime和endtime不连续,所以它将分别报告两条记录。看起来您的错误代码中有一个额外的结束括号。在您的子选项中可能有多余的*,它不会返回OP要求的数据@VBokšić。谢谢你摆好小提琴。我把grp排除在小组之外了。它现在起作用了:。不客气:仍然没有得到与这里相同的结果:我想得到以下结果:。@VBokšIć。这次已修复并检查。@Gordon Linoff它对我有效。非常感谢你的聪明方法!