好的,这在 MySQL 中并不漂亮。那是因为我们必须在子查询中伪造 rownum 值。
基本方法是将预订表的适当子集连接到自身偏移一。
这是项目 42 的基本预订列表,按预订时间排序。我们不能通过 booking_id 订购,因为不能保证按照预订时间的顺序。(你正试图在两个现有的预订之间插入一个新的预订,嗯?) http://sqlfiddle.com/#!2/62383/9/0
SELECT @aserial := @aserial+1 AS rownum,
booking.*
FROM booking,
(SELECT @aserial:= 0) AS q
WHERE item = 42
ORDER BY startdate, enddate
这是连接到自身的子集。诀窍是a.rownum+1 = b.rownum
,它将每一行与预订表子集中紧随其后的行连接起来。 http://sqlfiddle.com/#!2/62383/8/0
SELECT a.booking_id, a.startdate asta, a.enddate aend,
b.startdate bsta, b.enddate bend
FROM (
SELECT @aserial := @aserial+1 AS rownum,
booking.*
FROM booking,
(SELECT @aserial:= 0) AS q
WHERE item = 42
ORDER BY startdate, enddate
) AS a
JOIN (
SELECT @bserial := @bserial+1 AS rownum,
booking.*
FROM booking,
(SELECT @bserial:= 0) AS q
WHERE item = 42
ORDER BY startdate, enddate
) AS b ON a.rownum+1 = b.rownum
再次出现,显示每个预订(最后一个除外)及其后的小时数。 http://sqlfiddle.com/#!2/62383/15/0
SELECT a.booking_id, a.startdate, a.enddate,
TIMESTAMPDIFF(HOUR, a.enddate, b.startdate) gaphours
FROM (
SELECT @aserial := @aserial+1 AS rownum,
booking.*
FROM booking,
(SELECT @aserial:= 0) AS q
WHERE item = 42
ORDER BY startdate, enddate
) AS a
JOIN (
SELECT @bserial := @bserial+1 AS rownum,
booking.*
FROM booking,
(SELECT @bserial:= 0) AS q
WHERE item = 42
ORDER BY startdate, enddate
) AS b ON a.rownum+1 = b.rownum
因此,如果您正在寻找最早的十二小时时段的开始时间和结束时间,您可以使用该结果集来执行此操作: http ://sqlfiddle.com/#!2/62383/18/0
SELECT MIN(enddate) startdate, MIN(enddate) + INTERVAL 12 HOUR as enddate
FROM (
SELECT a.booking_id, a.startdate, a.enddate,
TIMESTAMPDIFF(HOUR, a.enddate, b.startdate) gaphours
FROM (
SELECT @aserial := @aserial+1 AS rownum,
booking.*
FROM booking,
(SELECT @aserial:= 0) AS q
WHERE item = 42
ORDER BY startdate, enddate
) AS a
JOIN (
SELECT @bserial := @bserial+1 AS rownum,
booking.*
FROM booking,
(SELECT @bserial:= 0) AS q
WHERE item = 42
ORDER BY startdate, enddate
) AS b ON a.rownum+1 = b.rownum
) AS gaps
WHERE gaphours >= 12