Как рассчитать непрерывный диапазон стола - PullRequest
1 голос
/ 24 сентября 2019

У меня есть следующая таблица:

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-код:

SELECT *
FROM (
  SELECT * 
    LEAD(EntityMid) OVER(PARTITION BY videoId ORDER BY StartTime) AS lead_EntityMid, 
    LEAD(EndTime) OVER(PARTITION BY videoId ORDER BY StartTime) AS lead_EndTime
)
FROM a
) b
WHERE EntityMid = lead_EntityMid 
AND EndTime + 1 = lead_EndTime

Ответы [ 2 ]

1 голос
/ 24 сентября 2019

Это форма проблемы пробелов и островков.

Для ваших конкретных данных вы можете использовать left join, чтобы определить, начинается ли «остров».Затем используйте кумулятивную сумму и агрегацию:

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;

Здесь - это db <> скрипка

0 голосов
/ 24 сентября 2019

Я уверен, что вы можете сделать это еще лучше и оптимизировать эту группу подзапросов, но сейчас это то, что я сделал:

Созданная таблица и вставленные значения:

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;

Скрипка: https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=0b05a3e10942640488b32c5285ec6158

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...