2015-07-09 3 views
0

Скажем, я хотел написать запрос, который найдет всех профессоров, доступных в произвольном временном интервале. У меня есть таблица профессоров и время, когда каждый профессор недоступен.Как создать запрос, который проверяет совпадения времени?

В таблице профессора есть запись для каждого профессора с их именем и слотом времени, в котором они заняты (поэтому у профессора с несколькими занятыми временными слотами будет несколько записей).

Моя проблема заключается в том, что если профессор уже занят в течение определенного временного интервала x, а также занят в другом временном интервале y, он вернет, что профессор доступен для x, потому что y не вмешивается.

Так что скажите, что мне нужно найти список профессоров, доступных в 12 часов. Профессор Джонс занят в 12 часов вечера, а также занят в 2 часа дня. Каждый запрос, который я придумываю, возвращает профессора Джонса как доступного для 12-часового слота, потому что он видит запись в 2 часа дня и знает, что это не перекрывается. (Фактический запрос должен быть общим, хотя он проходит через список временных интервалов и возвращает большую таблицу с каждым временным интервалом, и каждый профессор доступен в этом временном интервале, а не SELECT time WHERE time = "12")

+7

Шансы на получение любого ответа могут значительно увеличиться, если вы предоставите некоторую структуру таблицы, образцы данных и ожидаемый результат вместе с запросом, который вы уже пробовали, который не работает. Кроме того, вы используете Access или Oracle (или, возможно, оба)? – jpw

+0

Извините, я просто добавил немного больше информации. Я использую MS Access – Anon

+0

Является ли ваш столбец времени строкой? Вероятно, вы должны иметь время начала и окончания как время. Затем вы можете видеть, когда ваши профессора свободны, где время равно null. – Chuck

ответ

1

Основываясь на вашем описании и комментарии Я предполагаю, что вы имеете следующую структуру таблицы:

professor 
- name string 
- start datetime 
- end datetime 

неясно основано на описании ли вход для запроса один момент времени, или диапазон времени. Затем вы продолжаете упоминать, что решение должно быть «общим», чтобы оно проходило через «список временных интервалов». Что это за список? Где вы его получите? Для более тщательного ответа мне нужно, чтобы вы дали мне лучшее описание.

На данный момент я предполагаю, что вход для запроса представляет собой одно значение datetime, называемое $ checktime, и что вы пытаетесь найти список профессоров, которые доступны в тот момент времени , Это должно быть довольно просто изменить это на определенный промежуток времени.

Основываясь на описании проблемы с текущего запроса, это звучит, как текущий запрос что-то вроде этого:

SELECT DISTINCT name 
FROM professor 
WHERE $checktime < start 
    OR $checktime > end 

Если вы имели две записи, (Джонс, 12 вечера, 1pm) и (Jones , 2pm, 3pm) и выполнил этот запрос, используя $ checktime = 12pm, предложение where отфильтровывает первую запись, но вторая запись останется, оставив Jones в таблице результатов. Это похоже на описание, которое вы указали.

Хитрость здесь заключается в том, чтобы вместо этого найти список всех профессоров, которые заняты в то время, а затем использовать этот список, чтобы найти профессоров, которые не заняты в то время.

Например, начните со следующего запроса, который в основном является противоположным вашему текущему запросу.

SELECT DISTINCT name 
FROM professor 
WHERE $checktime >= start 
    AND $checktime <= end 

Это даст вам список всех профессоров, которые заняты в указанное время. Вы можете получить список всех профессоров и использовать МИНУС для удаления записей, содержащихся в предыдущем запросе:

(
-- The list of all professors 
SELECT DISTINCT name 
FROM professor 
) 
MINUS 
(
-- The list of all professors who are busy at the given time slot. 
SELECT DISTINCT name 
FROM professor 
WHERE $checktime >= start 
    AND $checktime <= end 
) 

Остальных профессора все профессора, которые не заняты данный момент.

Я не знаком с MS Access, но если это один из двигателей базы данных, который не поддерживает MINUS, вы можете вместо этого сделать следующее, которое логически эквивалентно (если у профессора таблицы есть ограничение на имя чтобы не быть пустым), но намного менее читаемыми:

SELECT DISTINCT all_profs.name 
FROM professor as all_profs 
LEFT JOIN 
    (SELECT DISTINCT name 
    FROM professor 
    WHERE $checktime >= start 
     AND $checktime <= end 
    ) as busy_profs 
ON all_profs.name = busy_profs.name 
WHERE busy_profs.name IS NULL 

в качестве примечания, вы должны рассмотреть вопрос об изменении структуры таблицы, так что напряженное время находятся в таблице отдельно от профессора, такие как новая таблица под названием busy_times с 3 столбцами: профессор (внешний ключ к таблице профессора), начало и конец. Это потому, что, по-видимому, у вас больше информации о профессоре, чем только их имена, и у большинства профессоров будет много занятых времен. Это приводит к много повторной информации, что плохо по двум причинам. Во-первых, он занимает гораздо больше места, чем нужно. Во-вторых, это очень громоздко поддерживать. Что произойдет, если профессор женится и изменит свое имя? Вам нужно будет изменить каждую запись, и если вы ее пропустили, это может вызвать проблемы.

+0

Спасибо за длинный ответ! Я прошу прощения за то, что вы так расплывчаты, я не хотел публично публиковать свою точную проблему, поэтому я составил ситуацию с профессором как пример. – Anon

Смежные вопросы