Каков принцип создания фильтра в интернет-магазине, не допускающего пустой результат?
Эта задача плохо ложится на реляционную СУБД, о чем вам уже писал Сергей Горностаев 
То, чем вы занимаетесь - это фасеточный поиск. Он прекрасно реализуется СУБД, умеющими т.н. полнотекстовый поиск.
Дело в том, что для реализации полнотекстового поиска используются битовые индексы, которые,помимо основной своей задачи поиска, позволяют сразу же определить и количество попавших в выборку "документов" (по терминологии: то, что называется "записями" в реляционных СУБД, то называется "документами" в движках полнотекстового поиска - такая традиция).
Вы же, используете неподходящую для этой задачи реляционную СУБД. А в реляционных СУБД определение количества записей, попавших в ответ, напротив - чрезвычайно долгая по времени операция.
Используя движок полнотекстового поиска вы могли бы применять фильтры просто, чтобы узнать сколько в результате ответа получится записей, а затем отключать их, если записей слишком много. В движках полнотекстового поиска это дешевая (быстрая) операция.
Но в реляционных СУБД, а вы пользуйтесь именно такой, - это очень накладная операция. И делать так нельзя. Если конечно вы не хотите чтобы у вас сайт тормозил.
Одним из самых скоростных движков полнотекстового поиска являются SphinxSearch и его форк Мантикора.
ПыСы:
Почему движки полнотекстового поиска идеально подходят под реализацию фасеточного поиска.
1) Поиск по названию все равно должен быть на сайте. Движок полнотекстового поиска, в отличие от обычного движка реляционных СУБД, может искать по любой части названия, по описанию товара...
2) Как строится полнотекстовый поиск и что он из себя представляет (вне нижеописанное делает движок полнотекстового поиска, вручную этого делать не надо):
а) Фраза разбивается на отдельные слова, при этом служебные слова (предлоги, союзы, артикли и т.п.) - отбрасываются
б) Слова прогоняются через алгоритм стемминга для отсечения окончаний snowball.tartarus.org/algorithms/russian/stemmer.html
в) Полученные слова без окончаний (термы) помещаются в простейшее хранилище типа "ключ-значение", где ключём является терм. Значением является большой битовый вектор типа 00010101011110010000000011111....., где каждой позиции нуля и единицы соответствует документ (в вашем случае - товар). Для компактности используется представление RoaringBitmap roaringbitmap.org
г) С полученными битовыми векторами можно чрезвычайно быстро делать любые логические операции AND, OR, NOT
Как делается фасеточный поиск на базе полнотекстового индекса?
Очень просто, вводим искусственный терм "цвет=зеленый", строим по нему битовый вектор; вводим искусственный терм "цвет=красный", строим по нему битовый вектор; вводим искусственный терм "вид=сапог" и строим по нему битовый вектор; вводим терм "вид=ботинок" и строим по нему битовый вектор; вводим термы "размер=40", "размер=41", "размер=42", "размер=43" и строим по каждому из них битовый вектор. 
После этого найти "ботинки зеленого цвета 42-го размера" - это всего лишь выполнить операцию AND по 3-м битовым векторам.
И еще раз - это все делает движок, вручную этого делать не нужно.
Любой движок взяли бы и посмотрели бы, зачем ВЕЛОСИПЕД изобретать?
Толковые фильтры есть и в опенкарт и в минишоп2 и в битрикс. 
Везде они естественно платные....
Хотя про битрикс я наверное зря, это не ваше))))
Минишоп - бесплатно ставите пакет miniShop2 + mSearch2 на демо-серверах, изучаете.
На демке как раз как вам нужно  - _minishop2.com/catalog/
Битрикс - бесплатно ставите демо-версию, ищите фильтр с бесплатной демо-установкой - всё! дальше неделю или сколько там даст разработчик фильтра - роетесь. 
А вот опенкарт казалось бы бесплатный по сути, а фильтр просто так не поставить, только предоплата))