Итак, исправляю сам себя.
Чтобы в наш интервал не попали 16 часов, он целиком должен помещаться между двумя ближайшими 16-часовыми отметками на временной прямой. Их можно получить искусственно: первая отметка это наиболее поздние дата-время, когда было 16 часов, но не позже, чем
start
, а вторая — ровно на сутки позже. Назовём условно эти отметки
a
и
b
. Так как
start
всегда попадает в
[a, b]
, вся задача сводится к проверке попадания
end
в интервал
[a, b]
. При
end < b
в интервале
[start, end]
не будет ни одной 16-часовой отметки. Теперь вернёмся к исходной задаче. Обращаем условие: при
end >= b
в интервал
[start, end]
попадёт хотя бы одна отметка в 16 часов.
Теперь постараемся получить
b
. Чтобы получить
a
, вычтем из
start
16 часов, обнулим временную часть (прыгнув таким образом к началу суток) и прибавим обратно 16 часов. Величину
b
получить ещё проще: прибавляем сутки к
a
.
И в SQL:
SELECT *
FROM my_table
WHERE
end >= DATE( start - INTERVAL '16:00:00' HOUR_SECOND ) + INTERVAL '16:00:00' HOUR_SECOND + INTERVAL 1 DAY