MySQL строгий выбор строк, включающих множество таблиц - PullRequest
0 голосов
/ 01 декабря 2008

У меня есть три таблицы в формате «многие ко многим». Т.е. таблицы A, B и AB настроены так, как вы ожидаете.

Учитывая некоторый набор идентификаторов A, мне нужно выбрать только те строки в AB, которые соответствуют всем идентификаторам.

Что-то вроде следующего не будет работать:

"ВЫБРАТЬ * ИЗ АБ, ГДЕ A_id = 1 И A_id = 2 И A_id = 3 И ..." Поскольку ни в одной строке не будет более одного A_id

Использование ИЛИ в SQL-описании не лучше, так как оно дает результаты всех результатов, которые имеют хотя бы один из идентификаторов A (тогда как я хочу только те строки, которые имеют все идентификаторы).

Edit:

Извините, я должен объяснить. Я не знаю, имеет ли отношение многие ко многим отношение к актуальной проблеме. Таблицы изложены следующим образом:

Table People
int id
char name

Table Options
int id
char option

Table peoples_options
int id
int people_id
int option_id

Итак, у меня есть список людей, список опций и таблица опций и людей.

Итак, учитывая список идентификаторов опций, таких как (1, 34, 44, ...), мне нужно выбрать только тех людей, у которых есть все опции.

Ответы [ 3 ]

1 голос
/ 01 декабря 2008

Ваша база данных не нормализуется правильно. Ваша таблица AB должна содержать один A_id и один B_id в каждой строке. Если бы это было так, ваша OR -версия должна работать (хотя я бы сам использовал IN).

Игнорировать предыдущий абзац. Из вашего редактирования вы действительно хотели знать все B, которые имеют все подмножества A в таблице «многие ко многим» - запрос см. Ниже.

Пожалуйста, сообщите нам фактические детали схемы, без этого немного сложно понять, что вы хотите.

Я бы ожидал увидеть что-то вроде:

table a:
    a_id integer
    a_payload varchar(20)
table b:
    b_id integer
    b_payload varchar(20)
table ab:
    a_id integer
    b_id integer

Исходя из вашего описания, я могу думать только о том, что вам нужен список всех B, которые имеют все наборы A в таблице AB. В этом случае вы смотрите что-то вроде (чтобы получить список B с A из 1, 3 и 4):

select distinct b_id from ab n1             
    where exists (select b_id from ab where a_id = 1 and b_id = n1.b_id)     
    and   exists (select b_id from ab where a_id = 3 and b_id = n1.b_id)     
    and   exists (select b_id from ab where a_id = 4 and b_id = n1.b_id);    

Это работает в DB2, но я не уверен, какую часть SQL реализует выбранный вами сервер.

0 голосов
/ 04 ноября 2014

Попробуйте это .... Он объединяет всех людей, связанных со всеми параметрами.

Другими словами, запрос выводит всех людей, что там не существует опции, не связанной с ним.


select
    p.*
from
    people p
where
    not exists (
              select 
                      1 
              from 
                      options o
              where
                      not exists 
                      (
                          select 1
                          from   peoples_options po 
                          where  po.people_id     = p.people_id
                                 AND po.option_id = o.option_id
                      )
           )
0 голосов
/ 01 декабря 2008

Немного хакерского решения - использовать IN с группой и с фильтром. Вот так:

SELECT B_id FROM AB
WHERE A_id IN (1,2,3)
GROUP BY B_id
HAVING COUNT(DISTINCT A_id) = 3;

Таким образом, вы получаете только значения B_id, которые имеют ровно 3 значения A_id, и они должны быть из вашего списка. Я использовал DISTINCT в COUNT на всякий случай (A_id, B_id) не уникален. Если вам нужны другие столбцы, вы можете присоединиться к этому запросу в качестве дополнительного выбора в предложении FROM другого оператора выбора.

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