Каждый курс может иметь (минимум И максимум) ИЛИ (определенное количество) участников.
Все курсы имеют минимум и максимум, для некоторых курсов это бывает одинаковое значение.Это может показаться тривиальным, но если подумать об этом, то вы сможете определить проблему проще.
Вместо:
min_students == X OR (min_students >= X AND max_students <= Y)
вы можете выразить это как:
num_students BETWEEN min_students AND max_students
BETWEEN
включительно, поэтому 8 BETWEEN 8 and 8
верно
Относительно оптимизаций
Дополнительные условия усложняют экспоненциально сложные запросы для людей, что приводит к пропущенным граничным случаям и обычно в любом случае приводит к неэффективным запросам.Сосредоточьтесь на том, чтобы сделать код легким для понимания или «элегантным», и никогда не жертвуйте удобочитаемостью для производительности, если вы не действительно уверены, что у вас есть проблема с производительностью, и ваша оптимизация действительно помогает.
Если у вас есть таблица с 10-миллионными строками, возможно, стоит обратить внимание на супероптимизацию использования диска, если вы работаете на крайне ограниченном hw, но сокращение использования диска таблицей даже с 20 МБ почти наверняка тратит время в любомнормальные обстоятельства, даже если это не делает код более сложным.
Кроме того, каждая строка занимает 23-24 байта в дополнение к любым фактическим данным, которые она содержит, так что бритье одного или двух байтов не будет иметь большого значения.Установка значений в NULL может на самом деле увеличить использование диска в некоторых ситуациях.
Альтернативное решение
При использовании типа данных диапазона сравнение будет выглядеть следующим образом:
num_students @> x
, где num_students
представляет диапазон (например, от 4 до 10)и @>
означает «содержит значение»
create table num_sequence (num int);
create table courses_range (name text, num_students int4range);
insert into num_sequence select generate_series(3,10);
insert into courses_range values
('math', '[4,4]'), ('physics', '[6,7]'), ('dance', '[7,9]');
select * from num_sequence
left join courses_range on num_students @> num;
num | name | num_students
-----+---------+--------------
3 | |
4 | math | [4,5)
5 | |
6 | physics | [6,8)
7 | physics | [6,8)
7 | dance | [7,10)
8 | dance | [7,10)
9 | dance | [7,10)
10 | |
Обратите внимание, что диапазоны выводятся в формате, аналогичном [x, y), жесткие скобки означают «включительно», а круглые скобки означают «исключение» и то, что для целых чисел: [4,4] = [4,5) = (3,5)