У меня есть лица: postes
и bookings
. Между poste
и booking
существует отношение oneToMany: у одного поста может быть много заказов (на разные даты).
bookings
определяется 4 столбцами:
booking_id
: id
poste_id
: соединение postes
стол
start_datetime
: дата начала бронирования
number_day
: количество дней (целое число)
postes
определяется 4 столбцами:
poste_id
: почтовый индекс
pattern
(строка): определен разрешенный день (1 разрешено, 0 нет). 8-й день определяется как 1-й день модели (по модулю 7)
start
: дата начала поста (все даты в бронировании указаны между началом и концом)
end
: конечная дата окончания
Цель : Я хотел бы определить запрос, который выбирает все postes
, которые не полностью зарезервированы (например, возможны некоторые новые резервирования). Я застрял, потому что я не могу выбрать какие-либо данные для свободного диапазона дат, так как хранятся только бронирования.
Пример * ** 1053 тысяча пятьдесят две *
Booking table
| booking_id | poste_id | start_datetime | number_day |
|------------|----------|----------------------|------------|
| 1 | 1 | 2019-07-10T00:00:00Z | 4 |
| 4 | 1 | 2019-07-14T00:00:00Z | 1 |
| 7 | 1 | 2019-07-16T00:00:00Z | 4 |
| 2 | 2 | 2019-07-10T00:00:00Z | 2 |
| 9 | 2 | 2019-07-13T00:00:00Z | 2 |
| 5 | 3 | 2019-07-15T00:00:00Z | 2 |
| 8 | 3 | 2019-07-21T00:00:00Z | 3 |
| 11 | 3 | 2019-07-28T00:00:00Z | 1 |
| 12 | 3 | 2019-07-29T00:00:00Z | 1 |
| 3 | 4 | 2019-07-15T00:00:00Z | 1 |
| 13 | 4 | 2019-07-21T00:00:00Z | 2 |
Postes table:
| poste_id | pattern | start | end |
|----------|---------|----------------------|----------------------|
| 1 | 1111101 | 2019-07-10T00:00:00Z | 2019-07-20T00:00:00Z |
| 2 | 1101101 | 2019-07-10T00:00:00Z | 2019-07-20T00:00:00Z |
| 3 | 1100001 | 2019-07-15T00:00:00Z | 2019-07-30T00:00:00Z |
| 4 | 1011001 | 2019-07-15T00:00:00Z | 2019-07-30T00:00:00Z |
Ожидаемый результат примера: 2,4
. (бронирование не доступно для почты 1
и 3
).
Примечание :
- Это простой пример. На самом деле, диапазоны дат больше, например в течение нескольких месяцев.
- В базе данных предполагается, что бронирования не перекрываются .
- Длина шаблона может отличаться от 7. Нет связи между первым днем шаблона и количеством дней в неделе. Например, если шаблон «1101» с начальной датой «10-07-2019», это означает, что доступны дни 10, 11, 13, 14, 15, 17 и т. Д., А не остальные.
- Даты бронирования всегда находятся между начальной и конечной датой
poste
.
воспроизводимость:
// Build the tables:
CREATE TABLE bookings
(`booking_id` int, `poste_id` int, `start_datetime` datetime, `number_day` int)
;
INSERT INTO bookings
(`booking_id`, `poste_id`, `start_datetime`, `number_day`)
VALUES
(1, 1, '2019-07-10', '4'),
(4, 1, '2019-07-14', '1'),
(7, 1, '2019-07-16', '4'),
(2, 2, '2019-07-10', '2'),
(9, 2, '2019-07-13', '2'),
(5, 3, '2019-07-15', '2'),
(8, 3, '2019-07-21', '3'),
(11, 3, '2019-07-28', '1'),
(12, 3, '2019-07-29', '1'),
(3, 4, '2019-07-15', '1'),
(13, 4, '2019-07-21', '2')
;
CREATE TABLE postes
(`poste_id` int, `pattern` VARCHAR(7), `start` datetime, `end` datetime);
INSERT INTO postes VALUES
(1, "1111101", "2019-07-10", "2019-07-20"),
(2, "1101101", "2019-07-10", "2019-07-20"),
(3, "1100001", "2019-07-15", "2019-07-30"),
(4, "1011001", "2019-07-15", "2019-07-30");
Моя работа : до сих пор мне удалось найти за данный день доступный пост:
SELECT DISTINCT p.*
FROM postes p
LEFT JOIN bookings b
ON b.poste_id = p.poste_id
WHERE
/* Ignore date in past */
MOD(DATEDIFF("2019-07-16", p.start), LENGTH(p.pattern)) >= -1
AND
/* Filter poste with pattern = 1 */
SUBSTRING(p.pattern, MOD(DATEDIFF("2019-07-16", p.start),
LENGTH(p.pattern)) + 1 , 1) = 1
AND
/* Filter those available this day */
p.poste_id NOT IN (
SELECT b.poste_id
FROM bookings b
WHERE b.start_datetime <= "2019-07-16"
AND "2019-07-16" < DATE_ADD(b.start_datetime, INTERVAL b.number_day DAY)
);
Выход:
| poste_id | pattern | start | end |
|----------|---------|----------------------|----------------------|
| 2 | 1101101 | 2019-07-10T00:00:00Z | 2019-07-20T00:00:00Z |