powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / MySQL [игнор отключен] [закрыт для гостей] / Фильтр для магазина (фасетный поиск)
14 сообщений из 14, страница 1 из 1
Фильтр для магазина (фасетный поиск)
    #39093338
gvozd1989
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Здравствуйте.
Я пишу быстрый фильтр для магазина OpenCart. Требуется фильтрация по атрибутам товара, цене, наличию скидки, категории и производителю. Подумав я решил сделать таблицу-кеш для всех вариаций опций:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
CREATE TABLE oc_product_filter (
  id int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
  store_id int(11) NOT NULL,
  product_id int(11) NOT NULL,
  `option` varchar(5) NOT NULL,
  value varchar(10) NOT NULL,
  label varchar(255) NOT NULL,
  PRIMARY KEY (id),
  INDEX product_id_idx (product_id),
  INDEX product_id_option_idx (product_id, `option`),
  INDEX store_option_value_idx (store_id, `option`, value)
)
ENGINE = INNODB
CHARACTER SET utf8
COLLATE utf8_general_ci;



Наполнил таблицу данными:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
id  store_id    product_id  option  value   label
15  0           107         11      78      17
19  0           107         18      125     Girl
21  0           107         19      126     0-24 month
1   0           107         m       21      Mothercare
17  0           107         13      270     Blue
4   0           107         pr      3       300-500
26  0           108         pr      2       150-300
48  0           108         18      125     Girl
50  0           108         19      126     0-24 month
42  0           108         11      67      12-18 month
44  0           108         13      56      Red 
46  0           108         13      61      Pink
23  0           108         m       20      Disney
25  0           108         sp      20      20%

И написал такой запрос:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
SELECT pf.*, COUNT(pf.value) as num
FROM oc_product_filter pf INNER JOIN
(
  SELECT DISTINCT product_id
  FROM oc_product_filter
  WHERE
    store_id = 0 AND
    (
      (`option` = '13' AND `value` = '270') OR
      (`option` = '11' AND `value` = '67')
    )
  GROUP BY product_id
  HAVING COUNT(product_id) = 2
) t ON pf.product_id = t.product_id
  WHERE pf.store_id = 0
GROUP BY pf.`option`, pf.value
ORDER BY `option` ASC , value ASC



Он работает быстро и хорошо, но есть одна проблема. Допустим мы фильтруем по категории и производителю, все другие группы рассчитаны верно, но в группе категория и производитель доступны только выбранные опции. Необходимо сделать возможность выбирать в одной категории двух производителей, то есть сделать множественный выбор. Возможно ли сделать это в одном запросе? Или у меня неправильная структура?
...
Рейтинг: 0 / 0
Фильтр для магазина (фасетный поиск)
    #39093389
вадя
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
gvozd1989,
подход в принципе не правильный
надо
таблиса товара
id_prod;name

таблица справочник атрибутов
id_spr; name

таблица атрибутов
id_attr;id_prod;id_spr;value_string;value_

тогда можно будет и добавлять любые атрибуты, и фильтровать как угодно
...
Рейтинг: 0 / 0
Фильтр для магазина (фасетный поиск)
    #39093391
вадя
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
поторопился
таблица српавочник имён товара
id_prod;name

таблица справочник атрибутов
id_spr; name

таблица товара
id_attr;id_prod;id_spr;value_string;value_
...
Рейтинг: 0 / 0
Фильтр для магазина (фасетный поиск)
    #39093401
tanglir
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
gvozd1989
Код: sql
1.
2.
3.
4.
SELECT pf.*, COUNT(pf.value) as num
FROM oc_product_filter pf <...>
GROUP BY pf.`option`, pf.value
ORDER BY `option` ASC , value ASC

"уж сколько раз твердили миру"...
...
Рейтинг: 0 / 0
Фильтр для магазина (фасетный поиск)
    #39093939
gvozd1989
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
вадя,
Сама таблица товаров есть. Если предположить, что есть таблица справочник атрибутов, то как будет выглядеть запрос?

tanglir,
Расшифруйте, пожалуйста, что имеется в виду?
...
Рейтинг: 0 / 0
Фильтр для магазина (фасетный поиск)
    #39094066
вадя
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
вот вариант с данными
damp
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
-- 
-- Отключение внешних ключей
-- 
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;

-- 
-- Установить режим SQL (SQL mode)
-- 
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;

-- 
-- Установка кодировки, с использованием которой клиент будет посылать запросы на сервер
--
SET NAMES 'utf8';

-- 
-- Установка базы данных по умолчанию
--
USE test;

--
-- Описание для таблицы attr_value
--
DROP TABLE IF EXISTS attr_value;
CREATE TABLE attr_value (
  id_attr_value INT(11) NOT NULL AUTO_INCREMENT,
  id_spr_name_attr INT(11) DEFAULT NULL,
  value_string VARCHAR(255) DEFAULT NULL,
  value_int INT(11) DEFAULT NULL,
  PRIMARY KEY (id_attr_value)
)
ENGINE = INNODB
AUTO_INCREMENT = 5
AVG_ROW_LENGTH = 4096
CHARACTER SET utf8
COLLATE utf8_general_ci;

--
-- Описание для таблицы spr_goods
--
DROP TABLE IF EXISTS spr_goods;
CREATE TABLE spr_goods (
  id INT(11) NOT NULL AUTO_INCREMENT,
  id_spr_name_goods INT(11) DEFAULT NULL,
  id_attr_value INT(11) DEFAULT NULL,
  PRIMARY KEY (id),
  UNIQUE INDEX UK_spr_goods_id_attr_value (id_attr_value)
)
ENGINE = INNODB
AUTO_INCREMENT = 3
AVG_ROW_LENGTH = 8192
CHARACTER SET latin1
COLLATE latin1_swedish_ci;

--
-- Описание для таблицы spr_name_attr
--
DROP TABLE IF EXISTS spr_name_attr;
CREATE TABLE spr_name_attr (
  id_spr_name_attr INT(11) NOT NULL AUTO_INCREMENT,
  name_attr VARCHAR(50) DEFAULT NULL,
  PRIMARY KEY (id_spr_name_attr)
)
ENGINE = INNODB
AUTO_INCREMENT = 3
AVG_ROW_LENGTH = 8192
CHARACTER SET utf8
COLLATE utf8_general_ci;

--
-- Описание для таблицы spr_name_goods
--
DROP TABLE IF EXISTS spr_name_goods;
CREATE TABLE spr_name_goods (
  id_spr_name_goods INT(11) NOT NULL AUTO_INCREMENT,
  name_good VARCHAR(50) DEFAULT NULL,
  PRIMARY KEY (id_spr_name_goods)
)
ENGINE = INNODB
AUTO_INCREMENT = 2
AVG_ROW_LENGTH = 16384
CHARACTER SET utf8
COLLATE utf8_general_ci;

-- 
-- Вывод данных для таблицы attr_value
--
INSERT INTO attr_value VALUES
(1, 1, 'МОсква', NULL),
(2, 1, 'питер', NULL),
(3, 2, NULL, 5),
(4, 2, NULL, 6);

-- 
-- Вывод данных для таблицы spr_goods
--
INSERT INTO spr_goods VALUES
(1, 1, 1),
(2, 1, 3);

-- 
-- Вывод данных для таблицы spr_name_attr
--
INSERT INTO spr_name_attr VALUES
(1, 'произв'),
(2, 'цена');

-- 
-- Вывод данных для таблицы spr_name_goods
--
INSERT INTO spr_name_goods VALUES
(1, 'мыло');

-- 
-- Восстановить предыдущий режим SQL (SQL mode)
-- 
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;

-- 
-- Включение внешних ключей
-- 
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;


запрос
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
SELECT
  spr_name_attr.name_attr,
  IF(ISNULL(attr_value.value_string), attr_value.value_int, attr_value.value_string) AS val,
  attr_value.id_attr_value,
  spr_name_goods.name_good
FROM spr_name_attr
  INNER JOIN attr_value
    ON spr_name_attr.id_spr_name_attr = attr_value.id_spr_name_attr
  INNER JOIN spr_goods
    ON attr_value.id_attr_value = spr_goods.id_attr_value
  INNER JOIN spr_name_goods
    ON spr_name_goods.id_spr_name_goods = spr_goods.id_spr_name_goods
WHERE spr_name_attr.name_attr = 'произв'
AND attr_value.value_string LIKE '%мос%'
OR spr_name_attr.name_attr = 'цена'
AND attr_value.value_int = 5



немного отличается от предыдущего
...
Рейтинг: 0 / 0
Фильтр для магазина (фасетный поиск)
    #39094079
Arhat109
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
gvozd1989,

tanglir имел ввиду, что скуль надо таки учить... :)
...
Рейтинг: 0 / 0
Фильтр для магазина (фасетный поиск)
    #39094333
gvozd1989
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
вадя,

Спасибо, но это немного не то, о чем я спрашивал. Меня интересует больше не сама фильтрация, а расчет возможных опций. К примеру выбрал одного производителя, и все опции пересчитали свое количество, но так, чтобы другие производители были не по 0, а чтоб их можно было добавить в фильтрацию.
...
Рейтинг: 0 / 0
Фильтр для магазина (фасетный поиск)
    #39094343
Фотография ScareCrow
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
бери сфинкс. на нём фасеты делаются почти из коробки.
...
Рейтинг: 0 / 0
Фильтр для магазина (фасетный поиск)
    #39094344
gvozd1989
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ScareCrow,

Я думал об этом, но хочу понять можно ли обойтись без него.
...
Рейтинг: 0 / 0
Фильтр для магазина (фасетный поиск)
    #39094427
вадя
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
gvozd1989,
ну так тут надо просто иметь знания как правильно составлять запросы
...
Рейтинг: 0 / 0
Фильтр для магазина (фасетный поиск)
    #39094850
tanglir
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
gvozd1989что имеется в виду?gvozd1989
Код: plaintext
1.
2.
id  store_id    product_id  option  value   label
19  0           107         18      125     Girl
48  0           108         18      125     Girl
Поставьте себя на место сервера, у которого есть вот такие данные в таблице, и скажите, что будет в красных полях в результате выполнения того запроса.
...
Рейтинг: 0 / 0
Фильтр для магазина (фасетный поиск)
    #39095039
gvozd1989
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
tanglir,

Спасибо, я понял о чем речь. Скажите, допустимо ли использовать в таком случае, GROUP BY CONCAT(pf.`option`, pf.value)?
...
Рейтинг: 0 / 0
Фильтр для магазина (фасетный поиск)
    #39095193
tanglir
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
gvozd1989,

похоже, всё-таки не поняли...
...
Рейтинг: 0 / 0
14 сообщений из 14, страница 1 из 1
Форумы / MySQL [игнор отключен] [закрыт для гостей] / Фильтр для магазина (фасетный поиск)
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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