У меня есть таблица products
. (идентификатор, наименование, цена), таблица называется properties
(идентификатор, название, тип) и таблицу с именем product_properties
(идентификатор, PROPERTY_ID, product_id, значение).SQL: Фильтровать продукты по списку
Теперь я могу фильтровать продукты следующим образом:
- Start со списком product_ids.
- Для каждого (свойство, значение), мы хотим, чтобы фильтровать по:
- product_ids =
SELECT 'product_properties'.'product_id' FROM 'product_properties' WHERE 'product_properties'.'product_id' IN [list,of,product,ids] AND 'product_properties'.'property_id' = property_id AND 'product_properties'.'value' = 'some value here'
- product_ids =
- Повторите шаг 2, пока мы не фильтруются все хотели свойства.
- Наконец, выберите все соответствующие продукты, используя
SELECT * FROM 'products' WHERE 'products'.'id' IN [list,of,product,ids]
Этот метод требует N + 1 запросов к базе данных для N фильтров. Я надеюсь, что это можно объединить в одном запросе.
Я попытался следующие, который не работает:
- INNER JOIN/OUTER JOIN -> Отменяет все product_properties указывая на продукт строк, кроме первой, а затем пытается обеспечить выполнение всех N идентификаторами и значения на нем.
- UNION -> Это возвращает список продуктов, которые соответствуют один или несколько фильтров, вместо все фильтры.
Как это может быть выполнено с помощью одного запроса базы данных (или как можно меньше)?
Я работаю с Ruby on Rails, а это значит, что я хотел бы, чтобы результат работал как в MySQL, так и в SQLite.
Спасибо!
OP запросил решение, совместимое с MySQL и SQLite. Хотя в начале 2014 года SQLite 3.8.3 предоставляет CTE, MySQL этого не делает, поэтому 'With()' не будет работать. – Parfait
Ничего себе! Метод UNION ALL ... GROUP BY ... HAVING COUNT() 'отлично работает. Очень хороший трюк. Большое спасибо! – Qqwy