У меня есть база данных, среди прочего, следующие две таблицы:
classes
is a straightforward table that has one row per class in a class schedule.
sessions
is a table that characterizes the days and times that each class meets, where each row is capable of expressing a notion like:
"Tuesdays | Jan 22-Mar 5 | 6-9pm"
"Tuesdays & Thursdays | Jan 22-Mar 7 | 6-9pm"
"Monday-Thursday | Jan 21-24 | 3-6pm"
"Saturday | Mar 9 | 9am-4pm"
и так далее.
Гарантируется, что по крайней мере одна строка в session
для каждой строки в классах
, а для определенных классов может быть две или несколько связанных строк сеанса.
В настоящее время я использую два разных запроса, чтобы получить информацию о классе и сеансе для классов, которые соответствуют определенному набору критериев, например:
select c.class_id, c.title, c.instructor, c.num_seats, c.price
from classes c
join classes_by_department cbd
on (cbd.class_id = c.class_id)
join /* several other tables */
on /* several other join conditions */
where cbd.department_id = '{$dept_id}'
and /* several other qualifying conditions */
;
и это:
select s.class_id, s.start_date, s.end_date, s.day_bits, s.start_time, s.end_time
from sessions s
join classes c
on (c.class_id = s.class_id)
join classes_by_department cbd
on (cbd.class_id = s.class_id)
join /* the same other tables */
on /* the same other join conditions */
where cbd.department_id = '{$dept_id}'
and /* the same other qualifying conditions */
;
Это отлично работает, и, по крайней мере, в текущем приложении - таблицы недостаточно велики, а трафик не достаточно тяжелый, так как два запроса являются проблемой. Тем не менее, это кажется мне немного расточительным, и мне интересно, не существует ли способа улучшить работу, уже выполненную первым запросом, для выполнения второго (вместо того, чтобы занять один и тот же запрос дважды и просто выберите разные столбцы).
Конечно, я понимаю, что я мог бы просто выбрать все соответствующие столбцы из classes
и sessions
в одном запросе (второй), но мне нравится тот факт, что в текущем подход, первый запрос предоставляет ровно одну строку для каждого класса, а не столько строк, сколько класс имеет записи сеанса. Мне нужно будет перестроить существующую логику, которая обрабатывает результаты запроса, если я объединил запросы. (Да, я знаю, ваа ...)
Одним из решений, которое пришло мне в голову, является сбор всех class_id
s, возвращенных первым запросом в вектор (так как я должен итерации по этим результатам) в любом случае, а затем форматировать содержимое этого вектора в качестве содержимого из списка значений для предложения IN
, так что второй запрос просто станет:
select s.class_id, s.start_date, s.end_date, s.day_bits, s.start_time, s.end_time
from sessions s
where s.class_id in (/* value-list */);
Я не слишком беспокоюсь о масштабируемости такого решения, так как я понимаю, что огромные SQL-запросы не имеют большого значения . Кроме того, он может использовать индекс, определенный над sessions.class_id
.
Но ... ну ... это просто не очень приятно для кого-то, кто хочет улучшить свои SQL-отбивные, которые я буду свободно признавать, довольно рудиментарны. Он чувствует себя неэлегантным и не очень «SQL-ish», или каким бы то ни было SQL-эквивалентом термина Pythonic .
Может ли кто-нибудь предложить что-то более подходящее?