MySQL严格选择涉及多对多表的行

时间:2008-12-01 01:56:26

标签: sql mysql many-to-many

我有多对多格式的三个表。即,表A,B和AB按照您的预期设置。

给定一组A id,我只需要选择AB中与所有id匹配的行。

以下内容不起作用:

“SELECT * FROM AB WHERE A_id = 1 AND A_id = 2 AND A_id = 3 AND ...” 因为没有一行会有多个A_id

使用,sql语句中的OR并不是更好,因为它会产生结果,所有结果至少有一个A ID(而我只希望那些具有所有id的行)。

修改

对不起,我应该解释一下。我不知道实际的多对多关系是否与实际问题相关。表格概述如下:

Table People
int id
char name

Table Options
int id
char option

Table peoples_options
int id
int people_id
int option_id

所以我有一个人员列表,一个选项列表,以及一个选项和人员表。

因此,给定一个选项ID列表,例如(1,34,44,...),我只需要选择那些拥有所有选项的人。

3 个答案:

答案 0 :(得分:1)

您的数据库似乎没有正确规范化。您的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

根据您的描述,我唯一能想到的就是您想要{{1}中包含所有BA的所有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。

答案 1 :(得分:0)

一个hacky解决方案是使用IN和group by并具有过滤器。像这样:

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

这样,您只能获得具有3个A_id值的B_id值,并且它们必须来自您的列表。我在COUNT中使用了DISTINCT,以防万一(A_id,B_id)不唯一。如果您需要其他列,则可以作为另一个select语句的FROM子句中的子选择加入此查询。

答案 2 :(得分:0)

试试这个....它会带来与所有选项相关联的所有人。

换句话说,查询会使所有人不存在与之无关的选项。


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
                      )
           )