Найти свободные даты в базе данных MySQL

260
12 мая 2017, 15:34

Необходимо: найти свободные промежутки дат не занятые диапазонами service_start - service_end.
На данный момент написал код, который работает, если есть только одно отношение classroom->service_id, где service_id не NULL. Если есть два таких, то ошибка:

Subquery returns more than 1 row

Прошу направить на правильный путь, какие операторы понадобятся для решение этой задачи: циклы (так как строк больше одной, видимо, они понадобятся, если есть), условные операторы или что-то еще. В MySQL нет таких глубокий знаний у меня. Или решения для подобной задачи.

mysql> select * from classrooms;
+--------------+-----------+------------+
| classroom_id | classroom | service_id |
+--------------+-----------+------------+
|            1 | 404       |          1 |
|            3 | 408       |          2 |
|            4 | 202       |       NULL |
+--------------+-----------+------------+
mysql> select * from services;
+------------+------------------------------------------------------------+---------------+---------------------+---------------------+
| service_id | service_name                                               | service_worth | service_start       | service_end         |
+------------+------------------------------------------------------------+---------------+---------------------+---------------------+
|          1 | Подготовка ЕГЭ: Русский язык                               |    10000.0000 | 2017-05-02 10:00:00 | 2017-05-11 10:00:00 |
|          2 | Подготовка ЕГЭ: Математика                                 |    10000.0000 | 2017-05-08 00:00:00 | 2017-05-10 00:00:00 |
|          3 | Подготовка ЕГЭ: Английский язык                            |    10000.0000 | 2017-04-27 00:00:00 | 2017-05-01 00:00:00 |
+------------+------------------------------------------------------------+---------------+---------------------+---------------------+
SELECT 
`classrooms`.`classroom_id`, 
`classrooms`.`classroom` 
FROM 
`classrooms` 
WHERE 
(
    `classrooms`.`service_id` IS NULL
) || (
    (
        SELECT 
            `services`.`service_start` 
        FROM 
            `services` 
            JOIN `classrooms` ON `services`.`service_id` = 
`classrooms`.`service_id` 
        WHERE 
            `services`.`service_id` = `classrooms`.`service_id`
    ) > (
        SELECT 
            `services`.`service_end` 
        FROM 
            `services` 
        WHERE 
            `services`.`service_id` = '$service_id'
    ) || (
        SELECT 
            `services`.`service_end` 
        FROM 
            `services` 
            JOIN `classrooms` ON `services`.`service_id` = `classrooms`.`service_id` 
        WHERE 
            `services`.`service_id` = `classrooms`.`service_id`
    ) < (
        SELECT 
            `services`.`service_start` 
        FROM 
            `services` 
        WHERE 
            `services`.`service_id` = '$service_id'
    )
)
Answer 1

Такой запрос решает поставленную задачу в вопросе:

SELECT
    c.classroom_id,
    c.classroom
FROM classrooms c
LEFT JOIN services s ON c.service_id = s.service_id
INNER JOIN services s1 ON s1.service_id = '$service_id'
WHERE c.service_id IS NULL
 OR (s.service_start >= s1.service_end
     OR s.service_end <= s1.service_start);

Но вам определенно стоит задуматься над переделкой БД. Например, добавить таблицу для конкретных занятий в рамках каждой услуги с полями service_id, lesson_id, lesson_start, lesson_end, classroom_id.

Answer 2

Создайте столбец busy и выставляете флаг, если строка (дата) занята, далее просто date >= service_start AND date <= service_end AND busy = 0

READ ALSO
История цен. Как правильно? MySQL

История цен. Как правильно? MySQL

Как правильно спроектировать таблицы, чтобы учитывать изменение цен на услугиЕсть две таблицы:

285
Выборка по точным вхождениям

Выборка по точным вхождениям

Реализована возможность динамического создания полей характеристик для товараЗадача: Сделать фильтр по характеристикам

240
Проставить изначальный zoom

Проставить изначальный zoom

Работаю с картами, как изначально проставить zoom(примерно так, чтоб было видно только тот город, в котором расположены эти маркеры)?

279
Взаимодействие между *.java-классами

Взаимодействие между *.java-классами

Всем приветЯ новичок в андроиде, поэтому много чего еще не понимаю

248