2

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

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

药片

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?(回答开斋节 2 和 5)
  2. 哪些 eid 有 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 的行。

我清楚我想要什么吗?

4

7 回答 7

7

使用集合减法

Select eid from t where fid = 'B' 
EXCEPT
select eid from t where fid = 'A'
于 2008-09-24T19:18:56.010 回答
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')
于 2008-09-24T19:25:34.853 回答
1

您可以使用子选择

选择 eid from t where fid = 'C' and eid not in (select eid from t where fid = 'A')

于 2008-09-24T19:23:18.947 回答
0

如 Nigel 和 Mike 所述,MySQL 5.0支持 where exists/where not exists。

于 2008-09-24T19:28:24.503 回答
0

具有可能比使用 EXISTS 更快的直接连接的版本:

选择 t1.eid
从#test t1
        左连接 (
            选择开斋节
            来自#test t2
            其中fid ='A'
            按开斋节分组
        ) t2 上 t2.eid = t1.eid
其中 t1.fid = 'B'
        并且 t2.eid 为空
于 2008-09-24T20:03:50.597 回答
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”。

于 2008-09-24T20:30:17.990 回答
0

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

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

select eid 
from t
where fid = 'A'
minus
select eid
from t
where fid = 'B'
于 2008-09-24T21:05:17.437 回答