Много ко многим запросам таблицы - PullRequest
2 голосов
/ 24 сентября 2008

У меня есть индексная таблица «многие ко многим», и я хочу выполнить для нее запрос типа include / exclude.

fid на самом деле является целочисленным индексом, но здесь в качестве букв для облегчения понимания. Вот пример таблицы:

таблица т

eid | fid
----+----
1   | A
1   | B
1   | C
2   | B
2   | C
3   | A
3   | C
4   | A
4   | B
5   | B

Вот несколько примеров запросов, которые я хочу.

  1. Какие eids имеют FID B, а НЕ A? (Ответ 2 и 5)
  2. Какие eids имеют FID C, а НЕ A? (Ответ еид 2)

Кажется, я не могу понять запрос, который сделает это.

Я пытался самостоятельно присоединиться, как это:

select * 
from t as t1 
join t as t2 
where t1.eid=t2.eid 
  and t1.fid!=t2.fid 
  and t1.fid=B and t2.fid!=A

Это не сработает, потому что все равно будет возвращать строки, где eid = 1 и fid = C.

Понятно ли, что я хочу?

Ответы [ 7 ]

7 голосов
/ 24 сентября 2008

Использовать установить вычитание

Select eid from t where fid = 'B' 
EXCEPT
select eid from t where fid = 'A'
3 голосов
/ 24 сентября 2008

Вот пример запроса для 1 (2 работает почти так же)

select t1.eid
  from t t1
 where t1.fid  = 'B'
   and not exists
       (select 1
          from t t2
         where t2.eid = t1.eid
           and t2.fid  = 'A')
1 голос
/ 24 сентября 2008

Вы можете использовать дополнительный выбор

выберите eid из t, где fid = 'C', и eid not in (выберите eid из t, где fid = 'A')

0 голосов
/ 25 сентября 2008

Посмотрите на оператора МИНУС. Он работает как UNION, за исключением того, что вычитает, куда добавляет UNION. Предыдущий ответ со словом «ИСКЛЮЧИТЬ» может быть другим ключевым словом для той же вещи.

Вот непроверенный ответ:

select eid 
from t
where fid = 'A'
minus
select eid
from t
where fid = 'B'
0 голосов
/ 25 сентября 2008

Должно быть возможно сделать это без использования подзапроса:

SELECT DISTINCT t1.eid
FROM table1 AS t1
  LEFT JOIN table1 AS t2 ON (t1.eid = t2.eid AND t2.fid = 'A')
WHERE t2.eid IS NULL
  AND t1.fid = 'B';

Чтобы выполнить второй пример поиска, просто измените значение «B» на «C».

0 голосов
/ 25 сентября 2008

Версия с прямыми соединениями, которая может быть быстрее, чем при использовании EXISTS:

Select  t1.eid
From    #test t1
        left join (
            Select  eid
            From    #test t2 
            Where   fid = 'A'
            Group by eid
        ) t2 on t2.eid = t1.eid 
Where   t1.fid = 'B'
        and t2.eid is null
0 голосов
/ 24 сентября 2008

MySQL 5.0 поддерживает где существует / где не существует, как описано Найджелом и Майком.

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