Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / MySQL [игнор отключен] [закрыт для гостей] / выборка с логикой И, в отношениях многие ко многим. / 18 сообщений из 18, страница 1 из 1
04.06.2015, 10:13:45
    #38975892
Лебедкин
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
выборка с логикой И, в отношениях многие ко многим.
есть таблица, реализующая отношение многие ко многим:

id1id2111211311212312113313

из нее легко выбираются объекты типа 2, которые имеют связи с объектами типа 1, заданные логикой ИЛИ:
Код: plsql
1.
select distinct id2 where id1 in (1,2);


получим:
11
12
13

а как выбрать объекты типа 2, которые связаны со ВСЕМИ заданными объектами типа 1?
т.е. при задании id1 (1 И 3) на выходе должны получиться 11, 13

чтоб понятнее было: Например, это связи поставщики и товары. Нужно выбрать поставщиков, которые поставляют (товар 1 И товар 3).
...
Рейтинг: 0 / 0
04.06.2015, 10:26:24
    #38975907
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
выборка с логикой И, в отношениях многие ко многим.
Лебедкин,

Код: plsql
1.
2.
3.
4.
select id2.id2 
from TABLE_OF_ID2 id2
where exists ( select * from LINK_TABLE l where l.id2 = id2.id2 and l.id1 = 1 )
  and  exists ( select * from LINK_TABLE l where l.id2 = id2.id2 and l.id1 = 2 )
...
Рейтинг: 0 / 0
04.06.2015, 10:45:23
    #38975926
Лебедкин
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
выборка с логикой И, в отношениях многие ко многим.
однако громоздко получается.
а если потом логика усложнится и понадобятся поставщики, поставляющие скажем:
(товар-1 И товар-3) ИЛИ (товар-2 И товар-4) ИЛИ (...) .... - будет вообще жуть :)

но принцип я понял, спасибо!
...
Рейтинг: 0 / 0
04.06.2015, 11:01:49
    #38975949
Akina
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
выборка с логикой И, в отношениях многие ко многим.
Со всеми заданными в списке:
Код: sql
1.
2.
3.
4.
5.
SELECT id2
FROM table
WHERE id1 IN (1,3)
GROUP BY id2
HAVING COUNT(DISTINCT id1) = 2


Со всеми имеющимися в таблице:
Код: sql
1.
2.
3.
4.
SELECT id2
FROM table
GROUP BY id2
HAVING COUNT(DISTINCT id1) = ( SELECT COUNT(DISTINCT id1) FROM table )
...
Рейтинг: 0 / 0
04.06.2015, 11:22:30
    #38975979
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
выборка с логикой И, в отношениях многие ко многим.
Лебедкиноднако громоздко получается.
а если потом логика усложнится и понадобятся поставщики, поставляющие скажем:
(товар-1 И товар-3) ИЛИ (товар-2 И товар-4) ИЛИ (...) .... - будет вообще жуть :)


Ничего ни жуткого, ни громоздкого.
Ты громоздкие запросы просто не видел никогда в жизни.
Громоздкие -- это листов на 5-10.
...
Рейтинг: 0 / 0
04.06.2015, 11:23:27
    #38975982
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
выборка с логикой И, в отношениях многие ко многим.
AkinaСо всеми заданными в списке:
Код: sql
1.
2.
3.
4.
5.
SELECT id2
FROM table
WHERE id1 IN (1,3)
GROUP BY id2
HAVING COUNT(DISTINCT id1) = 2


Со всеми имеющимися в таблице:
Код: sql
1.
2.
3.
4.
SELECT id2
FROM table
GROUP BY id2
HAVING COUNT(DISTINCT id1) = ( SELECT COUNT(DISTINCT id1) FROM table )



Неопримально.
Запрос делает много ненужной работы, а именно, сначало всё группируется, затем фильтруется.
Плохо.
...
Рейтинг: 0 / 0
04.06.2015, 11:40:55
    #38976013
Akina
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
выборка с логикой И, в отношениях многие ко многим.
Угу... а коррелированные подзапросы (и пропущенный тобой DISTINCT) - это типа оптимально... особенно когда количество сверяемых типов не задано жёстко или вообще неизвестно заранаа.
...
Рейтинг: 0 / 0
04.06.2015, 14:02:51
    #38976234
Лебедкин
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
выборка с логикой И, в отношениях многие ко многим.
Akina,

до подобных способов, основанных на подсчете количества совпадений, а сам додумывался.
однако это не будет работать если понадобится логика типа: (товар-1 И товар-3) ИЛИ товар-2.
а решение, которое показал MasterZiv, в этом плане более универсальное.
...
Рейтинг: 0 / 0
04.06.2015, 14:35:14
    #38976282
Akina
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
выборка с логикой И, в отношениях многие ко многим.
Лебедкиноднако это не будет работать если понадобится логика типа: (товар-1 И товар-3) ИЛИ товар-2.
Если логика столь многообразна - можно переходить на суммирование условных выражений:
Код: sql
1.
2.
3.
4.
5.
SELECT id2
FROM table
GROUP BY id2
HAVING (SUM(id1 IN (1,3)) = 2) 
    OR (SUM(id1 IN (2)) = 1)


Подобный подход позволяет легко строить достаточно сложные условия отбора, например:
Код: sql
1.
2.
3.
4.
5.
6.
SUM (id1 IN (1,2,3,4,5)) BETWEEN 2 AND 4 -- от 2 до 4 товаров из 5 заданных
SUM (id1 IN (1,2,3,4,5)) >= 3 -- не менее 3 товаров из 5 заданных
SUM (id1 IN (1,2,3,4,5)) < 3 -- строго менее 3 товаров из 5 заданных
SUM (id1 IN (1,2,3,4,5)) = 0 -- ни одного товара из 5 заданных
SUM (id1 IN (1,2,3,4,5)) = 3 -- строго 3 товара из 5 заданных
SUM (id1 IN (1,2,3,4,5)) = 5 -- строго все товары из 5 заданных


Причём любое количество таких частных условий могут объединяться произвольным способом с использованием логических операций и скобок, а сами суммируемые условия могут включать несколько полей:
Код: sql
1.
SUM((id1 IN (11,12,13)) AND (id2 > id1)) > 1


И получающееся суммарное выражение при этом останется достаточно легко читаемым.

Решение, которое показал MasterZiv, при таких требованиях превратится в сущий кошмар даже чисто синтаксически - не говоря уж о динамическом построении текста запроса. Оно хорошо лишь в достаточно частных случаях при малом количестве отборов - попробуй с его подходом построить запрос для выборки с условием "от 2 до 4 товаров из 5 заданных" или задав полсотни, а не два, товаров, и сразу поймёшь, что я имею в виду.
...
Рейтинг: 0 / 0
04.06.2015, 15:24:24
    #38976373
Лебедкин
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
выборка с логикой И, в отношениях многие ко многим.
Akina,

ого! и правда, гибко и круто!
Хотя мне такая гибкость пока ненужна, это я так на перспективу закладываюсь.
Я даже не знал что можно так: SUM(id1 IN (1,3) -- (ну я в SQL пока еще много чего не знаю :)
возьму ваш способ на вооружение. спасибо.
...
Рейтинг: 0 / 0
04.06.2015, 15:40:09
    #38976397
Akina
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
выборка с логикой И, в отношениях многие ко многим.
ЛебедкинЯ даже не знал что можно такЭто особенность MySQL - он интерпретирует (преобразует) True в плюс единицу, да к тому же всегда приводит типы к нужным, если это возможно (даже когда его не просят). На других СУБД такой фортель не пройдёт, там придётся обкладывать всё это CASE-ами.
...
Рейтинг: 0 / 0
07.06.2015, 08:20:30
    #38978313
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
выборка с логикой И, в отношениях многие ко многим.
AkinaЛебедкиноднако это не будет работать если понадобится логика типа: (товар-1 И товар-3) ИЛИ товар-2.
Если логика столь многообразна - можно переходить на суммирование условных выражений:
Код: sql
1.
2.
3.
4.
5.
SELECT id2
FROM table
GROUP BY id2
HAVING (SUM(id1 IN (1,3)) = 2) 
    OR (SUM(id1 IN (2)) = 1)


Подобный подход позволяет легко строить достаточно сложные условия отбора, например:
Код: sql
1.
2.
3.
4.
5.
6.
SUM (id1 IN (1,2,3,4,5)) BETWEEN 2 AND 4 -- от 2 до 4 товаров из 5 заданных
SUM (id1 IN (1,2,3,4,5)) >= 3 -- не менее 3 товаров из 5 заданных
SUM (id1 IN (1,2,3,4,5)) < 3 -- строго менее 3 товаров из 5 заданных
SUM (id1 IN (1,2,3,4,5)) = 0 -- ни одного товара из 5 заданных
SUM (id1 IN (1,2,3,4,5)) = 3 -- строго 3 товара из 5 заданных
SUM (id1 IN (1,2,3,4,5)) = 5 -- строго все товары из 5 заданных


Причём любое количество таких частных условий могут объединяться произвольным способом с использованием логических операций и скобок, а сами суммируемые условия могут включать несколько полей:
Код: sql
1.
SUM((id1 IN (11,12,13)) AND (id2 > id1)) > 1


И получающееся суммарное выражение при этом останется достаточно легко читаемым.

Решение, которое показал MasterZiv, при таких требованиях превратится в сущий кошмар даже чисто синтаксически - не говоря уж о динамическом построении текста запроса. Оно хорошо лишь в достаточно частных случаях при малом количестве отборов - попробуй с его подходом построить запрос для выборки с условием "от 2 до 4 товаров из 5 заданных" или задав полсотни, а не два, товаров, и сразу поймёшь, что я имею в виду.

вы не то оптимизируете, критерий у вас неверный.

вот , чтобы примерно представить, как выглядит мало-мальски громоздкий запрос:
www.sql.ru/forum/1160179/pomogite-optimizirovat-zapros

этот вот запрос

SELECT id2
FROM table
GROUP BY id2
HAVING (SUM(id1 IN (1,3)) = 2)
OR (SUM(id1 IN (2)) = 1)


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

так писать можно только если у тебя очень маленькая эта таблица и гарантировано не будет расти.
...
Рейтинг: 0 / 0
07.06.2015, 20:18:46
    #38978512
Akina
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
выборка с логикой И, в отношениях многие ко многим.
MasterZiv , верно, фуллскан гарантирован. Впрочем, столь же гарантированно - однопроходный.
Я вообще ничего не оптимизирую. Я упрощаю задачу шаблонизации. Да и не было такой задачи - оптимизировать.
...
Рейтинг: 0 / 0
08.06.2015, 14:01:38
    #38978995
Arhat109
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
выборка с логикой И, в отношениях многие ко многим.
MasterZiv,

Да ладно вам ... как жеж "не оптимизируется" когда перечень товаров задается через IN() ? :)

Кто мешает дополнить так:
SELECT id2
FROM table
GROUP BY id2
WHERE id1 IN(1,2,3)
HAVING (SUM(id1 IN (1,3)) = 2)
OR (SUM(id1 IN (2)) = 1)

и отобрать только те записи из линков, где заведомо присутствуют ТОЛЬКО искомые товары? Не, тут "фуллскан" только когда нам ВСЯ таблица связи интересна...

P.S. Сам давно пользуюсь таким методом. Просто и наглядно.
...
Рейтинг: 0 / 0
08.06.2015, 15:49:59
    #38979181
alex564657498765453
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
выборка с логикой И, в отношениях многие ко многим.
давайте будем обьективными...речь идёт о фильтре...

и раз тут задаёться вопрос, то максимальная посещаемость этого мега-ресурса в интернете будет до 10 человек в неделю...100 максимум...да пусть хоть на пхп или чёмтам вытаскивает записи все и работая с масивами шаманит... и сойдёт.

сначала человеку надо работающий код, потом только делать что б код работал правильно, потом надёжно в случае ошибок в данных, а потом уже думать про оптимально.

ЗЫ
у меня было фильтр ...10 величин, в половине возможне выбор нескольких значений...

взял товары которые

условие один И
условие два-один или условие два-два
....

и нормально... ну 5000 записей...ну доростёт до 30к хотя єто уже фантастика, размотрим даже за гранью - 50к, ну доростёт посещаемьсть... до 1000 человек в неделю... и что?

тем более что на таблицу сделаны индексы парные по логике...ну скажем страна и производитель.... или там цвет+комната (закащик сказал что он уверен, что кто фильтрует обои по комнате будет и по цвету )

вообщем пара индексов на разпространённые подходы к выбору обоев. и нормально... тормоза у сайта есть - офигенно красивый фронд-енд, чуть ли ни в ШД качестве с долбисораундом.
...
Рейтинг: 0 / 0
08.06.2015, 18:10:55
    #38979465
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
выборка с логикой И, в отношениях многие ко многим.
Arhat109MasterZiv,

Да ладно вам ... как жеж "не оптимизируется" когда перечень товаров задается через IN() ? :)

Кто мешает дополнить так:
SELECT id2
FROM table
GROUP BY id2
WHERE id1 IN(1,2,3)
HAVING (SUM(id1 IN (1,3)) = 2)
OR (SUM(id1 IN (2)) = 1)


Ну да, но это же статичный фильтр, то, что и так понятно, т.е. статичное усечение множества того, где нам искать,
а не то, что мы ищим.
Т.е. это небольшое отсечение кол-ва записей (если большое -- всё шикарно).
А то, что мы ищем, эти условия, они зашиврованы в этом запросе в

Код: plaintext
1.
2.
HAVING (SUM(id1 IN (1,3)) = 2)
OR (SUM(id1 IN (2)) = 1)

И множество записей результата формируется толко на финальном этапе этого запроса.
...
Рейтинг: 0 / 0
08.06.2015, 18:11:47
    #38979466
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
выборка с логикой И, в отношениях многие ко многим.
alex564657498765453давайте будем обьективными...речь идёт о фильтре...

и раз тут задаёться вопрос, то максимальная посещаемость этого мега-ресурса в интернете будет до 10 человек в неделю...100 максимум..

Да если так -- то вообще всё шикарно!
...
Рейтинг: 0 / 0
09.06.2015, 08:26:15
    #38979712
Arhat109
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
выборка с логикой И, в отношениях многие ко многим.
MasterZiv,

Конечно. Это действительно статичный фильтр. ТС его описал своим вопросом "а как выбрать...". И никаких особых проблем с формированием выборки возникать не должно хоть на 10 товарах хоть на 10000 ... а вот то, что он банально удобен и подчиняется регулярной сборке - важно. Его легко можно генерировать каким-нить "запросо-генератором" и практически произвольной сложности и в т.ч. и с "отсечением".

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


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