SQLinfo.ru - Все о MySQL Webew.ru: теория и практика веб-технологий

Форум пользователей MySQL

Задавайте вопросы, мы ответим

Вы не зашли.

#1 14.02.2015 17:11:01

yellowcat
Участник
Зарегистрирован: 09.11.2010
Сообщений: 19

Поиск по характеристикам

Добрый день.

Есть таблица:


CREATE TABLE IF NOT EXISTS `product2performance` (
  `product_id` int(7) NOT NULL,
  `performance_id` int(7) NOT NULL,
  PRIMARY KEY (`product_id`,`performance_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

--
-- Дамп данных таблицы `product2performance`
--

INSERT INTO `product2performance` (`product_id`, `performance_id`) VALUES
(1, 1),
(1, 4),
(1, 7),
(2, 1),
(2, 4),
(2, 6),
(3, 2),
(3, 5),
(3, 6),
(4, 3),
(4, 4),
(4, 6);
 


Она связана с таблицами performance и product связью многие ко многим.

Задача в следующем: нужно найди ID товаров, которые соответствуют условию performance_id = ((1 OR 3) AND 4 AND (6 OR 7))

То есть товары у которых есть характеристики (смотрите вложение)

или (Красный,Шестиструнный,Gibson)
или (Красный,Шестиструнный,Fender)
или (Черный,Шестиструнный,Gibson)
или (Черный,Шестиструнный,Fender)

Ничего умнее join таблицы саму на себя придумать не могу:

SELECT t1.`product_id`
FROM `product2performance` as t1, `product2performance` as t2, `product2performance` as t3
WHERE 1 = 1
AND (t1.performance_id = 1 OR t1.performance_id = 3)
AND (t2.performance_id = 4)
AND (t3.performance_id = 6 OR t3.performance_id = 7)
AND t1.product_id = t2.product_id
AND t2.product_id = t3.product_id
 


Данный запрос прекрасно работает. Но если количество категорий характеристик будет возрастать вместе с их значениями,то запрос окажется слишком сложным и медленным.

Помогите найти более изящное решение задачи. Спасибо

Отредактированно yellowcat (14.02.2015 17:12:55)


Прикрепленные файлы:
Attachment Icon 940d21e4af.jpg, Размер: 30,356 байт, Скачано: 619

Неактивен

 

#2 14.02.2015 20:46:44

vasya
Архат
MySQL Authorized Developer
Откуда: Орел
Зарегистрирован: 07.03.2007
Сообщений: 5842

Re: Поиск по характеристикам

SELECT `product_id`
FROM `product2performance`
WHERE performance_id = ((1 OR 3) AND 4 AND (6 OR 7))
GROUP BY `product_id`
HAVING count(*)=3;

Неактивен

 

#3 15.02.2015 12:15:18

yellowcat
Участник
Зарегистрирован: 09.11.2010
Сообщений: 19

Re: Поиск по характеристикам

vasya написал:

SELECT `product_id`
FROM `product2performance`
WHERE performance_id = ((1 OR 3) AND 4 AND (6 OR 7))
GROUP BY `product_id`
HAVING count(*)=3;

Ваш запрос не работает:

MySQL вернула пустой результат (т.е. ноль строк). ( запрос занял 0.0032 сек. ) в то время как мой запрос возвращал 3 записи...

Вот рабочий вариант, на основе вашей идеи с count и having

SELECT `product_id`
FROM `product2performance`
WHERE
performance_id IN (1,4,7)
OR performance_id IN (1,4,6)
OR performance_id IN (3,4,6)
OR performance_id IN (3,4,7)
GROUP BY `product_id`
HAVING count(*)=3

Есть ли еще более изящное решение? Спасибо

Отредактированно yellowcat (15.02.2015 12:29:03)

Неактивен

 

#4 16.02.2015 10:01:36

vasya
Архат
MySQL Authorized Developer
Откуда: Орел
Зарегистрирован: 07.03.2007
Сообщений: 5842

Re: Поиск по характеристикам

Да, это я скопировал условие из постановки задачи не задумавшись.

Оптимальный вариант:

SELECT `product_id`
FROM `product2performance`
WHERE
performance_id IN (1,3,4,6,7)
GROUP BY `product_id`
HAVING count(*)=3

Ну и индекс на performance_id.
Чем обусловлен порядок полей в primary?

Неактивен

 

#5 16.02.2015 13:03:56

yellowcat
Участник
Зарегистрирован: 09.11.2010
Сообщений: 19

Re: Поиск по характеристикам

vasya написал:

Да, это я скопировал условие из постановки задачи не задумавшись.

Оптимальный вариант:

SELECT `product_id`
FROM `product2performance`
WHERE
performance_id IN (1,3,4,6,7)
GROUP BY `product_id`
HAVING count(*)=3

Ну и индекс на performance_id.
Чем обусловлен порядок полей в primary?

Спасибо. Запрос работает нормально.

Порядок полей в primary обусловлен тем, что пара должна быть уникальна. + я использую yii, а там это вроде бы как обязательное условие.
а что с ними не так?

Неактивен

 

#6 16.02.2015 14:27:48

vasya
Архат
MySQL Authorized Developer
Откуда: Орел
Зарегистрирован: 07.03.2007
Сообщений: 5842

Re: Поиск по характеристикам

Уникальность пары от порядка полей в индексе не зависит.
Для того, чтобы искать продукт по характеристикам (как, например, в запросе выше) нужна другая последовательность - (`performance_id`,`product_id`)

Подробнее можно посмотреть FAQ №5

Неактивен

 

#7 17.02.2015 13:43:57

yellowcat
Участник
Зарегистрирован: 09.11.2010
Сообщений: 19

Re: Поиск по характеристикам

спасибо. не первый раз выручаете!

Неактивен

 

Board footer

Работает на PunBB
© Copyright 2002–2008 Rickard Andersson