Задать вопрос

Как составить «хитрый» MySQL запрос?

Здравствуйте! Подскажите пожалуйста, как это сделать лучше, и как это сделать вообще.

Есть в БД MySQL таблица, в которой присутствуют 2 столбца TIMESTAMP: start, end.

start — дата+время начала некоего процесса, end — конца.

Нужно выбрать все записи, у которых временной отрезок [start,end] охватывает, скажем 16:00, т.е. за это время часы хоть раз, но показали 16:00.

Например:

01-01-2012 12:00; 01-01-2012 18:00 — подходит, а

01-01-2012 17:00; 01-01-2012 18:00 — не подходит, а

01-01-2012 23:00; 02-01-2012 17:00 — подходит.


SELECT * FROM `table` WHERE ?????


В MySQL не гуру. Буду очень благодарен!


PS вначале случайно поместил не в вопросы, а в посты. Кто успел увидеть — всем «простите» :-)
  • Вопрос задан
  • 7749 просмотров
Подписаться 10 Оценить Комментировать
Решения вопроса 1
FloppyFormator
@FloppyFormator
Итак, исправляю сам себя.

Чтобы в наш интервал не попали 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
Ответ написан
Пригласить эксперта
Ответы на вопрос 4
@himik
select * from table where '16:00:00' between CAST(start AS DATE) and CAST(end AS TIME)

не проверял, но что-то вроде этого должно работать
Ответ написан
@betal
start_time < 16:00 AND end_time > 16:00 OR start_time > end_time
Если ничего не упустил можно как-то так попробовать.
Ответ написан
FloppyFormator
@FloppyFormator
Предлагаю идти от обратного: в какой интервал не попадает время 16 часов? Только в такой, который целиком помещается между 16 часами первого и следующего дня. То есть, нужно проверить, попадает ли наш интервал в этот промежуток. Пересечение интервалов [a, b] и [c, d] легко проверяется условием a <= d && b >= c. В нашем случае, start >= next_date_16_00 && end <= start_date_16_00, где start_date_16_00 — 16 часов в день начала интервала, а next_date_16_00 — то же, но на следующие сутки. Обращаем условие (мы ведь начинали от обратного): start < next_date_16_00 || end > start_date_16_00.

И наш запрос:
SELECT *
FROM my_table
WHERE
    start < TIMESTAMP( DATE(start) + INTERVAL 1 DAY, '16:00:00' ) OR
    end > TIMESTAMP( DATE(start), TIME('16:00:00') )
Ответ написан
@Vampiro
А я бы добавил в таблицу поле "продолжительность", (или вместо "дата завершения") И имел запрос
((время начала + продолжительность)по модулю 24) >= нужная точка

where MOD(`start`+`length`,24)>=16
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы