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

Mysql SQL连接表在开始和结束之间的时间,mysql,sql,closest,Mysql,Sql,Closest,我有两张桌子: Events (ID, Name, Time, Recorder) Video (ID, StartTime, EndTime, Recorder, Filename) 我希望将事件数据加入到视频数据中,以便为每个事件获取视频文件名。记录器字段用于指定事件发生时可操作的记录器,并协助多个记录器同时录制视频 如果我不关心没有视频的事件,那么这很好,我可以得到SQL,但是在我的例子中,我希望显示最接近的视频文件名和秒数差 编辑 样本数据 事件 1, EV1, 2012-01-01

我有两张桌子:

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
录像带

结果 EventID、VideoID、文件名、IsBetween、秒差异

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 
奖金


如果最近的视频没有考虑到录像机,而是考虑到第一个边界开始和结束检查,我会更好。如果这太难,那就好了。

有点笨重,但我想到了以下几点:

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行,但现在,我在groupby中输入一行,只选择一行

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

我的最终结果是:

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为null的所有事件

它产生的结果与赞恩的答案相同


非常感谢Zane。

您能提供样本数据和预期结果吗?startTime、EndDateTime和Time字段是否同时包含日期和时间?是否应根据输入时间是否接近startTime或endtime返回该字段?另外,视频字段中的ID是否引用了事件表中的ID字段?@Zane Bien-它应该只返回从开始或结束到最近的视频文件,不,ID在两个表之间没有链接,明白吗!我看看能想出什么办法。我喜欢这样的挑战。哦,顺便问一下,会不会有一个活动直接在视频日期范围之间?i、 e.“2012-01-01 12:15”如果是的话,它是否应该返回它与开始日期之间的差值(如果它更接近开始日期),而结束日期是否应该返回它与开始日期之间的差值?@Zane Bien,是的,可能存在介于日期范围之间的事件。在这种情况下,我唯一的要求是我需要区分视频时间和外部时间之间的事件。如果需要,可能会返回一个IsBetween字段+1谢谢-这确实会产生正确的输出,但是关于clunky:,您是对的。我设法对它进行了一些优化,速度快了10倍左右
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