SQL在开始和结束之间的时间连接表

时间:2012-06-14 04:12:39

标签: mysql sql closest

我有两张桌子:

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

我希望将事件数据加入到视频数据中,以便为每个事件获取视频文件名。录音机字段用于指定在事件发生时哪个录音机可操作,并协助多个录音机同时录制视频。

如果我不关心没有视频的事件,那么这很好(我可以得到SQL),但在我的情况下,我希望显示最接近的视频文件名和秒差。

修改

样本数据

活动

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,Filename,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 

奖金

如果最近的视频没有考虑录音机,我会更好(但是第一个界限(开始和结束)检查将其考虑在内)如果这太难了那么那很好。

2 个答案:

答案 0 :(得分: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来选择一行。

让我知道它是如何运作的。

答案 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

基本上,这首先获取没有任何视频的所有事件,然后将此结果加入整个视频列表,通过EventIDClosestSeconds对其进行排序,然后按{{1}对结果进行分组删除重复项。最后,我需要删除EventID为空的任何事件。

它产生的结果与Zane的答案相同。

非常感谢Zane。