多对多的表查询

时间:2008-09-24 19:16:17

标签: sql join

我有多对多的索引表,我想对它进行包含/排除类型查询。

fid实际上是一个整数索引,但这里作为字母以便于理解。这是一个示例表:

表t

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

以下是我想要的一些示例查询。

  1. 什么eid有fid B,而不是A? (回答eid 2和5)
  2. 哪些eid有fid,而不是A? (回答eid 2)
  3. 我似乎无法弄清楚会执行此操作的查询。

    我尝试过像这样的自我加入:

    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 个答案:

答案 0 :(得分:7)

使用set subtraction

Select eid from t where fid = 'B' 
EXCEPT
select eid from t where fid = 'A'

答案 1 :(得分:3)

以下是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')

答案 2 :(得分:1)

您可以使用子选择

从t中选择eid,其中fid ='C'且eid not in(从t中选择eid,其中fid ='A')

答案 3 :(得分:0)

MySQL 5.0支持存在/不存在的位置,如Nigel和Mike所述。

答案 4 :(得分:0)

具有直接连接的版本可能比使用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

答案 5 :(得分:0)

应该可以在不使用子查询的情况下执行此操作:

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”。

答案 6 :(得分:0)

查看MINUS运算符。它像UNION一样工作,除了它减去UNION添加的地方。带有“EXCEPT”字样的上一个答案可能是同一事物的不同关键字。

这是一个未经测试的答案:

select eid 
from t
where fid = 'A'
minus
select eid
from t
where fid = 'B'