Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / MySQL [игнор отключен] [закрыт для гостей] / Система фильтров / 5 сообщений из 5, страница 1 из 1
28.03.2014, 22:33:46
    #38599638
Luft-on
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Система фильтров
Добрый день уважаемые форумчане, передо мной встала задача сделать систему фильтров для интернет-магазина. Имеется несколько подручных таблиц: product, category, filter, filter_value, product_filter_value.
Соответственно
Таблица product хранит записи о товарах;

Таблица category хранит записи о категориях товаров;

Таблица filter хранит записи о фильтрах, фильтры связаны с категориями товаров внешним ключом, здесь храниться общая информация о фильтре: название, тип, настройки отображения на сайте и т.п.;

Таблица filter_value хранит доступные значения фильтров, например, цвета, размеры, марки производителей, а также, числовые значения фильтров, например, массу, мощность, объём и т.д., значения фильтров связаны с самими фильтрами внешним ключом;

Таблица product_filter_value связывает товары со значениями фильтров.

Теперь запрос для выбора, например карт памяти объёмом 4 или 8 Гб выглядит так:
Код: sql
1.
2.
3.
4.
5.
SELECT t.* FROM product p
INNER JOIN product_filter_value pfv ON p.id=pfv.productId
INNER JOIN filter_value fv ON pfv.filterValueId=fv.id
WHERE ((published=1) AND (categoryId IN (18)))
AND ((fv.filterId=1) AND (pfv.filterValueId IN (3, 4)))


Здесь 1 - id фильтра "Объём карты памяти", а 3 и 4 - id записей из таблицы filter_value и им соответствуют значения 4 и 8 Гб

А запрос для выбора карт памяти от производителя Kingston так:
Код: sql
1.
2.
3.
4.
5.
SELECT t.* FROM product t
INNER JOIN product_filter_value pfv ON t.id=pfv.productId
INNER JOIN filter_value fv ON pfv.filterValueId=fv.id
WHERE ((published=1) AND (categoryId IN (18)))
AND ((fv.filterId=2) AND (pfv.filterValueId=25))


Здесь 2 - id фильтра "Производитель карты памяти", а 25 - id записи из таблицы filter_value и ей соответствует значение Kingston.

А как сделать запрос для выбора карт памяти объёмом 4 или 8 Гб от производителя Kingston? Если объеденить оба условия, то в результате получается 0 пересечений.
...
Рейтинг: 0 / 0
28.03.2014, 23:59:43
    #38599664
SharuPoNemnogu
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Система фильтров
fv.filterId IN (1,2) ?
...
Рейтинг: 0 / 0
29.03.2014, 13:34:28
    #38599810
Luft-on
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Система фильтров
SharuPoNemnogufv.filterId IN (1,2) ?
Тогда получается условие должно выглядеть так?
Код: sql
1.
((fv.filterId IN (1, 2)) AND (pfv.filterValueId IN (3, 4, 25)))



По идее это пройдёт, и даже можно уброть fv.filter IN ... потому что pfv.filterValueId и так связан внешним ключом с filter, а как быть если нужно ещё и условие:
Код: sql
1.
(fv.filterId=3) AND (fv.value BETWEEN 1200 AND 1800)


Здесь filterId - id числового фильтра, скажем мощности пароварки, а 1200 и 1800 сами значения.
...
Рейтинг: 0 / 0
29.03.2014, 14:53:31
    #38599838
SharuPoNemnogu
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Система фильтров
Код: sql
1.
(fv.filterId IN (1, 2) AND pfv.filterValueId IN (3, 4, 25)) OR (fv.filterId=3 AND (fv.value BETWEEN 1200 AND 1800))



Составляйте условия динамически и связывайте их через OR. потом в запрос. Я так понимаю php используется же.
...
Рейтинг: 0 / 0
29.03.2014, 16:29:13
    #38599866
Luft-on
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Система фильтров
SharuPoNemnogu
Код: sql
1.
(fv.filterId IN (1, 2) AND pfv.filterValueId IN (3, 4, 25)) OR (fv.filterId=3 AND (fv.value BETWEEN 1200 AND 1800))



Составляйте условия динамически и связывайте их через OR. потом в запрос. Я так понимаю php используется же.

Да, использую PHP, только в таком варианте выберутся как пароварки с мощностью от 1200 и до 1800, так и пароварки конкретного производителя, потому что условия объеденены оператором ИЛИ, а нужно выбрать пароварки определённой мощности + определённого производителя.

Пока решил очень жестоко: для каждого фильтра выбираю GROUP_CONCAT(p.id SEPARATOR ",") as ids и на стороне сервера делаю array_intersect с предыдущим массивом id-шников товаров. После выполнения данной операции для всех фильтров получаю перечень id товаров подходящих под все фильтры. Можно ещё наверное упростить задачу если в каждом последующем запросе указывать критерий IN по полю id товара, передавая как список id товаров которые уже подходят под фильтры.
...
Рейтинг: 0 / 0
Форумы / MySQL [игнор отключен] [закрыт для гостей] / Система фильтров / 5 сообщений из 5, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]