Оптимизация запросов [новичок]
От: koenjihyakkei Россия  
Дата: 03.12.14 14:22
Оценка:
Ситуация такая.
Есть таблица с полями product_id и category_id. Связи много-много.
На входе: 1 — список категорий и 2 — список категорий-исключений.
На выходе: список товаров, входящие в категории первого списка, но не входящие в категории второго списка.

В общем, алгоритм топорный:
Делаю запрос выбора товаров по первому списку, получаю список товаров, потом в цикле для каждого товара (и каждой категории-исключения) делаю запрос примерно такого вида:
SELECT EXIST( SELECT 1 FROM table WHERE prod_id = cat_id_exclude)

Если 1, то не включаю товар в результирующий список, иначе включаю.

Вроде все работает, но когда выбираю большое количество категорий-исключений, все виснет очень надолго. Что тут можно оптимизировать?

ЗЫ: Сильно не ворчите, я с БД никогда не работал. А тут подруга попросила цены у нее в магазине повысить, вот и тыкаюсь, а времени совсем мало...
ЗЫЗЫ: PHP, MySQL, Joomla, Virtuemart
Re: Оптимизация запросов [новичок]
От: BlackEric http://black-eric.lj.ru
Дата: 03.12.14 15:07
Оценка: 6 (2)
Здравствуйте, koenjihyakkei, Вы писали:

K>Ситуация такая.

K>Есть таблица с полями product_id и category_id. Связи много-много.
K>На входе: 1 — список категорий и 2 — список категорий-исключений.
K>На выходе: список товаров, входящие в категории первого списка, но не входящие в категории второго списка.

А написать
 Select * from table where
(product_id in category_1) and (product_id not in category_1)
https://github.com/BlackEric001
Re: Оптимизация запросов [новичок]
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 03.12.14 22:56
Оценка: +2
Здравствуйте, koenjihyakkei, Вы писали:

K>Ситуация такая.

K>Есть таблица с полями product_id и category_id. Связи много-много.
K>На входе: 1 — список категорий и 2 — список категорий-исключений.
K>На выходе: список товаров, входящие в категории первого списка, но не входящие в категории второго списка.

select ... 
from products p
join categories c on c.Id = p.CategoryId
left join exclusion ex on c.Id = e.Id
where e.Id is null


И все, субд разберется что и как надо джоинить (циклы, merge, hash-join)

Правда в MySQL настолько убогий оптимизатор, что возможно придется хинтами пинать.
Re[2]: Оптимизация запросов [новичок]
От: koenjihyakkei Россия  
Дата: 06.12.14 11:15
Оценка:
Здравствуйте, BlackEric, Вы писали:

BE>А написать

BE>
BE> Select * from table where
BE>(product_id in category_1) and (product_id not in category_1)
BE>


Спасибо, попробовал, но результат немного не тот что нужен:

http://sqlfiddle.com/#!2/5b105/7/0

CREATE TABLE test
    (
      category_id int,
      product_id int
    );

INSERT INTO test
(category_id, product_id)
VALUES
(1, 10),
(1, 11),
(1, 12),
(1, 13),
(2, 12),
(2, 13),
(2, 14),
(2, 15),
(2, 16);


SELECT * FROM test WHERE (category_id IN (1,2)) AND (category_id NOT IN (2))


Результат:
CATEGORY_ID PRODUCT_ID
1 10
1 11
1 12
1 13

а нужен такой
CATEGORY_ID PRODUCT_ID
1 10
1 11

То есть все продукты, входящие в обе категории должны исключаться.
Re[2]: Оптимизация запросов [новичок]
От: koenjihyakkei Россия  
Дата: 06.12.14 11:19
Оценка:
Здравствуйте, gandjustas, Вы писали:

Я совсем некурящий в SQL поэтому немного не понимаю ваш синтаксис как это будет выглядеть для такой базы:

CREATE TABLE test
    (
      category_id int,
      product_id int
    );

INSERT INTO test
(category_id, product_id)
VALUES
(1, 10),
(1, 11),
(1, 12),
(1, 13),
(2, 12),
(2, 13),
(2, 14),
(2, 15),
(2, 16);
Re[3]: Оптимизация запросов [новичок]
От: AndrewN Россия  
Дата: 06.12.14 20:01
Оценка: 2 (1)
Здравствуйте, koenjihyakkei, Вы писали:

K>Здравствуйте, BlackEric, Вы писали:


BE>>А написать

BE>>
BE>> Select * from table where
BE>>(product_id in category_1) and (product_id not in category_1)
BE>>


K>Спасибо, попробовал, но результат немного не тот что нужен:


K>http://sqlfiddle.com/#!2/5b105/7/0


K>
K>CREATE TABLE test
K>    (
K>      category_id int,
K>      product_id int
K>    );

K>INSERT INTO test
K>(category_id, product_id)
K>VALUES
K>(1, 10),
K>(1, 11),
K>(1, 12),
K>(1, 13),
K>(2, 12),
K>(2, 13),
K>(2, 14),
K>(2, 15),
K>(2, 16);


K>SELECT * FROM test WHERE (category_id IN (1,2)) AND (category_id NOT IN (2))
K>


K>Результат:

K>CATEGORY_ID PRODUCT_ID
K>1 10
K>1 11
K>1 12
K>1 13

K>а нужен такой

K>CATEGORY_ID PRODUCT_ID
K>1 10
K>1 11

K>То есть все продукты, входящие в обе категории должны исключаться.



Ну тогда вычтите результат второго запроса из первого и всё

SELECT product_id FROM test WHERE category_id IN(1)
MINUS
SELECT product_id FROM test WHERE category_id IN(2)
--------------------------------------------------------------
Правильно заданный вопрос содержит в себе половину ответа
Re[4]: Оптимизация запросов [новичок]
От: koenjihyakkei Россия  
Дата: 07.12.14 19:14
Оценка:
Здравствуйте, AndrewN, Вы писали:

AN>Ну тогда вычтите результат второго запроса из первого и всё


AN>
AN>SELECT product_id FROM test WHERE category_id IN(1)
AN>MINUS
AN>SELECT product_id FROM test WHERE category_id IN(2)
AN>


Оказывается в Mysql нет оператора MINUS, но говорят LEFT JOIN делает то же самое, но проверить толком не смог, так как при гуглении увидел одну интересную конструкцию с вложенным селектом, решил попробовать у себя.. и взлетело как надо )
Получилось вот так:

SELECT product_id
FROM test
WHERE category_id IN(1,2) 
  AND product_id NOT IN(
    SELECT product_id
    FROM test
    WHERE category_id IN(2))
Re: Оптимизация запросов [новичок]
От: seregaa Ниоткуда http://blogtani.ru
Дата: 09.12.14 21:08
Оценка:
Здравствуйте, koenjihyakkei, Вы писали:

K>Ситуация такая.

K>Есть таблица с полями product_id и category_id. Связи много-много.
K>На входе: 1 — список категорий и 2 — список категорий-исключений.
K>На выходе: список товаров, входящие в категории первого списка, но не входящие в категории второго списка.

SELECT distinct product_id 
FROM test 
WHERE 
      category_id IN (1,2) AND 
      not exists (select * from test excl where excl.product_id = test.product_id and excl.category_id IN (2))
Мобильная версия сайта RSDN — http://rsdn.org/forum/rsdn/6938747
Автор: sergeya
Дата: 19.10.17
Re: Оптимизация запросов [новичок]
От: MasterZiv СССР  
Дата: 31.12.14 07:12
Оценка:
Здравствуйте, koenjihyakkei, Вы писали:

K>Ситуация такая.

K>Есть таблица с полями product_id и category_id. Связи много-много.
K>На входе: 1 — список категорий и 2 — список категорий-исключений.
K>На выходе: список товаров, входящие в категории первого списка, но не входящие в категории второго списка.

K>В общем, алгоритм топорный:

K>Делаю запрос выбора товаров по первому списку, получаю список товаров, потом в цикле для каждого товара (и каждой категории-исключения) делаю запрос примерно такого вида:
K>
K>SELECT EXIST( SELECT 1 FROM table WHERE prod_id = cat_id_exclude)
K>

K>Если 1, то не включаю товар в результирующий список, иначе включаю.

K>Вроде все работает, но когда выбираю большое количество категорий-исключений, все виснет очень надолго. Что тут можно оптимизировать?


Написать сразу одним запросом, естественно.
У тебя тупо если много категорий-исключений, то много походов к серверу, а именно их Кол-во выбранных товаров * кол-во категорий -исключений.
Re[2]: Оптимизация запросов [новичок]
От: koenjihyakkei Россия  
Дата: 31.12.14 10:00
Оценка:
Здравствуйте, MasterZiv, Вы писали:

MZ>Написать сразу одним запросом, естественно.

MZ>У тебя тупо если много категорий-исключений, то много походов к серверу, а именно их Кол-во выбранных товаров * кол-во категорий -исключений.

ага, уже написал одним запросом, вот так http://rsdn.ru/forum/db/5882956.1
Автор: koenjihyakkei
Дата: 07.12.14
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.