powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / MySQL [игнор отключен] [закрыт для гостей] / Поиск записей при связи многие ко многим
9 сообщений из 9, страница 1 из 1
Поиск записей при связи многие ко многим
    #39234207
Int_20h
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Имеется запрос вида
Код: sql
1.
select Goods.* from Goods left join Goods_Categories using (GoodsID)



связь Goods с Categories - многие ко многим через таблицу Goods_Categories

Необходимо отбирать GoodsID, входящие в категории, как по правилу И, так и ИЛИ. Например:

только GoodsID, входящие в категории (2 или 3) и одновременно с этим входящие в категории (5 или 8 или 17) и одновременно в категории (7 или 4).

При таком запросе из таблицы вида:

GoodsID CategoriesID
1 2
1 8
1 4
2 1
2 2
2 6

должен быть отобран только GoodsID = 1. Пока приходит в голову только вложенная структура с кучей объединений, что наверное не правильно.

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
select * 
from Goods 
where GoodsID in 
  (select GoodsID 
   from Goods_Categories GC1 
    join Goods_Categories GC2 using (GoodsID) 
    join Goods_Categories GC3 using (GoodsID) 
   where GC1.CategoriesID in (2,3) and GC2.CategoriesID in (5,8,17) and GC3.CategoriesID in (7,4)
  )


Сейчас в таблице 17 000 записей. При 3 джоинах они превращаются в 2 509 528. А если таких джоинов будет 5 или 6?!!!

Подскажите, какими методами обычно решают подобные задачи?
...
Рейтинг: 0 / 0
Поиск записей при связи многие ко многим
    #39234394
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Такие задачи решают группировкой и пост-отбором по наложенным ограничениям.авторНапример:

только GoodsID, входящие в категории (2 или 3) и одновременно с этим входящие в категории (5 или 8 или 17) и одновременно в категории (7 или 4).
Код: sql
1.
HAVING SUM(category in (2,3)) AND SUM(category in (5,8,17)) AND SUM(category in (4,7)) 
...
Рейтинг: 0 / 0
Поиск записей при связи многие ко многим
    #39234751
Int_20h
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Akina,

Великолепное решение, спасибо большое. Сейчас еще проверю, будет ли такой запрос кэшироваться.

С одной стороны, насколько я понимаю, HAVING не оптимизируется встроенным оптимизатором, кроме того, запросы с функциями не кэшируются. С другой стороны, функции то простые, на одном и том же наборе данных должны возвращать одинаковые значения.... Может закэшируется, тогда все вообще идеально будет.
...
Рейтинг: 0 / 0
Поиск записей при связи многие ко многим
    #39234811
tanglir
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Int_20hHAVING не оптимизируется встроенным оптимизатором,во-первых, что там в принципе можно "оптимизировать"?
во-вторых, а разве есть какой-то другой оптимизатор?
...
Рейтинг: 0 / 0
Поиск записей при связи многие ко многим
    #39235885
Int_20h
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Akina,

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

Иногда нужно считать количество товаров в выборке. Раньше я просто делал count в селекте и все:

select count(distinct GoodsGen.GoodsID) from GoodsGen left join GoodsGroups using (GoodsID) left join GoodsCategories using (GoodsID) where GoodsGen.Deleted = 0 and GoodsGen.Archived = 0 and GoodsGroups.GroupsID in (79) group by GoodsGen.GoodsID having SUM(GoodsCategories.CategoriesContentsID in (136)) order by GoodsGen.OrderNum asc

Сейчас же он считает строки внутри Group by и я получаю все строки с единицами. Как лучше обойти данную проблему?
...
Рейтинг: 0 / 0
Поиск записей при связи многие ко многим
    #39235886
Int_20h
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Запрос с форматированием из предыдущего сообщения
Код: sql
1.
select count(distinct GoodsGen.GoodsID) from GoodsGen left join GoodsGroups using (GoodsID) left join GoodsCategories using (GoodsID) where GoodsGen.Deleted = 0 and GoodsGen.Archived = 0 and GoodsGroups.GroupsID in (79) group by GoodsGen.GoodsID having SUM(GoodsCategories.CategoriesContentsID in (136)) order by GoodsGen.OrderNum asc
...
Рейтинг: 0 / 0
Поиск записей при связи многие ко многим
    #39235888
Int_20h
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Пока сделал вложенный запрос:

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
SELECT count( DISTINCT PreSelect.GoodsID )
FROM (
   SELECT GoodsGen.GoodsID AS GoodsID
   FROM GoodsGen
   LEFT JOIN GoodsGroups
   USING ( GoodsID )
   LEFT JOIN GoodsCategories
   USING ( GoodsID )
   WHERE GoodsGen.Deleted =0
   AND GoodsGen.Archived =0
   AND GoodsGroups.GroupsID
   IN ( 79 )
   GROUP BY GoodsGen.GoodsID
   HAVING SUM( GoodsCategories.CategoriesContentsID IN ( 44, 69 ) )
   ORDER BY GoodsGen.OrderNum ASC
) AS PreSelect



Есть ли способы эффективнее?
...
Рейтинг: 0 / 0
Поиск записей при связи многие ко многим
    #39235907
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
tanglirInt_20hHAVING не оптимизируется встроенным оптимизатором,во-первых, что там в принципе можно "оптимизировать"?
во-вторых, а разве есть какой-то другой оптимизатор?


поддерживаю.
только exist с подзапросом!
...
Рейтинг: 0 / 0
Поиск записей при связи многие ко многим
    #39236229
tanglir
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Int_20h,

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


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