2012-06-14 2 views
3

У меня есть две таблицы:SQL Регистрация таблиц по времени между началом и концом

Events (ID, Name, Time, Recorder) 
Video (ID, StartTime, EndTime, Recorder, Filename) 

Я хотел бы присоединиться к информации о событиях в видеоданными, так что для каждого события я получаю видео файла. Поле регистратора используется для указания того, какой рекордер был работоспособен во время события, и помогает одновременно записывать видео на несколько записывающих устройств.

Если меня не интересовали события, у которых нет видео, тогда это нормально (я могу получить SQL), однако в моем случае я хочу показать самое близкое имя файла видео и разницу секунд.

EDIT

Примеры данных

События

1, EV1, 2012-01-01 12:00, A 
2, EV2, 2012-01-01 13:00, B 
3, EV3, 2012-01-01 12:15, B 
4, EV4, 2012-01-01 11:45, A 

Видео

1, 2012-01-01 12:00, 2012-01-01 12:30, A, 1.mpg 
2, 2012-01-01 13:00, 2012-01-01 13:30, A, 2.mpg 
3, 2012-01-01 12:00, 2012-01-01 12:30, B, 3.mpg 

Результат (EventID, VideoID, имя файла, IsBetween, SecondsDifference)

1, 1, 1.mpg, TRUE, 0 
2, 3, 3.mpg, FALSE, 1800 //1800 seconds from the end of video 3 
3, 3, 3.mpg, TRUE, 900 
4, 1, 1.mpg, FALSE, 900 //900 seconds from the start of video 1 

БОНУС

Я бы еще лучше, если ближайшие видео не брали диктофон во внимание (но первые оценки (Start и End) проверьте, чтобы принять его во внимание) Если это слишком сложно то это прекрасно.

+0

Можете ли вы привести данные о выборке и ожидаемый результат? Поля startTime, EndDateTime и Time содержат как дату, так и время? –

+0

Должен ли он вернуть тот, на основе того, если он (время ввода) ближе к началу или концу? Кроме того, есть ли идентификатор в поле видео, связанное с полем «ID» в таблице «События»? –

+0

@ Zane Bien - Он должен просто вернуть самый близкий видеофайл (от начала или до конца) и нет, идентификаторы не связаны между двумя таблицами – Simon

ответ

2

Это немного неуклюжее, но вот что я придумал:

SELECT 
    * 
FROM 
    (
     SELECT 
      a.ID AS EventID, 
      b.ID AS VideoID, 
      b.Filename, 
      (
       CASE 
        WHEN a.Time < b.StartTime THEN UNIX_TIMESTAMP(b.StartTime) - UNIX_TIMESTAMP(a.Time) 
        WHEN a.Time > b.EndTime THEN UNIX_TIMESTAMP(a.Time) - UNIX_TIMESTAMP(b.EndTime) 
       END 
      ) AS distance_factor 
     FROM 
      `Events` a 
     CROSS JOIN 
      video b 
     WHERE 
      NOT EXISTS 
      (
       SELECT NULL 
       FROM Video 
       WHERE a.Time BETWEEN StartTime AND EndTime 
      ) 
    ) c 
WHERE 
    c.distance_factor = 
    (
     SELECT 
      MIN(CASE WHEN d.Time < e.StartTime THEN UNIX_TIMESTAMP(e.StartTime) - UNIX_TIMESTAMP(d.Time) WHEN d.Time > e.EndTime THEN UNIX_TIMESTAMP(d.Time) - UNIX_TIMESTAMP(e.EndTime) END) 
     FROM 
      `Events` d 
     CROSS JOIN 
      video e 
     WHERE d.ID = c.EventID 
    ) 
GROUP BY 
    c.EventID 

Это возвращает события, чьи даты не попадет между любым из временных диапазонов любого видео, но затем возвращает видео, попадающее ближе к этой дате события.

Единственное, что прямо сейчас в том, что есть несколько видеороликов, где разница секунд точно такая же. Я не знаю, хотите ли вы вернуть 2 строки, но пока я ввел GROUP BY, чтобы просто выбрать один.

Дайте мне знать, как это работает.

+0

+1 Спасибо - это действительно дает правильный результат, но вы правы насчет неуклюжих :). Мне удалось немного его оптимизировать и примерно в 10 раз быстрее – Simon

+1

Отлично! Не могли бы вы поделиться тем, что вы сделали, чтобы его оптимизировать? –

2

Мой конечный результат был:

SELECT * FROM 
    (SELECT * FROM 
     (SELECT * FROM 
      (SELECT *, (CASE WHEN Time < StartTime THEN UNIX_TIMESTAMP(StartTime) - UNIX_TIMESTAMP(Time) 
        WHEN Time > EndTime THEN UNIX_TIMESTAMP(Time) - UNIX_TIMESTAMP(EndTime) 
       END 
       ) AS SecondsDifference 

      FROM 
      (
       SELECT * FROM Events E 
        LEFT JOIN Video V ON (E.Time >= V.StartTime AND E.Time <= V.EndTime) 
        WHERE DVID IS NULL GROUP BY E.EventID 
      ) A ORDER BY A.EventID, A.SecondsDifference 
    ) B GROUP BY EventID 
) C WHERE C.SecondsDifference IS NOT NULL 

По сути, это первый получает все события без каких-либо видео, а затем присоединяется этот результат на весь список видео, приказы его по EventID и ClosestSeconds, а затем группы Результата EventID, чтобы удалить дубликаты. Наконец, мне нужно было удалить любые события, где SecondsDifference был нулевым.

Он дает тот же результат, что и ответ Зейна.

Большое спасибо Zane.

Смежные вопросы