Sql 选择匹配多对多联接表中所有组的记录

Sql 选择匹配多对多联接表中所有组的记录,sql,mysql,Sql,Mysql,我有两张桌子:集合和分组。两者都使用第三个表集\u has\u组连接。 我希望得到包含我指定的所有组的集合 一种方法是 SELECT column1, column2 FROM sets WHERE id IN(SELECT set_id FROM set_has_group WHERE group_id = 1) AND id IN(SELECT set_id FROM set_has_group WHERE group_id = 2) AND id IN(SELECT set_id FRO

我有两张桌子:集合和分组。两者都使用第三个表集\u has\u组连接。 我希望得到包含我指定的所有组的集合

一种方法是

SELECT column1, column2 FROM sets WHERE 
id IN(SELECT set_id FROM set_has_group WHERE group_id = 1)
AND id IN(SELECT set_id FROM set_has_group WHERE group_id = 2)
AND id IN(SELECT set_id FROM set_has_group WHERE group_id = 3)
显然,这不是最漂亮的解决方案

我也试过:

SELECT column1, column2 FROM sets WHERE 
id IN(SELECT set_id FROM set_has_group WHERE group_id IN(1,2,3) GROUP BY group_id
HAVING COUNT(*) = 3
这看起来更漂亮,但问题是它需要永远执行。 第一个查询大约运行200毫秒,而第二个查询则需要1分钟以上

知道为什么吗

==更新: 我又玩了一些,我修改了第二个查询如下

SELECT columns FROM `set` WHERE id IN(
   select set_id FROM
      (
         SELECT set_id FROM set_has_group 
         WHERE group_id IN(1,2,3)
         GROUP BY set_id HAVING COUNT(*) = 3
      ) as temp         
)
那真的很快 这与之前的第二个查询相同,只是我将其包装在另一个临时表中
非常奇怪

我怀疑在第二个查询中有一点输入错误

真的,我不确定。第二个查询可能是通过完整表扫描执行的。同时,第一个“在”真的转化为“存在”。因此,您可以尝试使用“exists”。例如:

...
where 3 = (select count(*) from set_has_group 
    where group_id in (1, 2, 3) and set_id = id
    group by set_id)

假设使用SQL Server,这里是一个具有联接的工作示例,只要主键和外键设置正确,该联接应比您正在使用的IN子句工作得更好。我已经将5个集合加入到3个组中,但集合4和集合5不是第3组的一部分,因此不会显示在答案中。但是,此查询不可伸缩(例如,组4、5、7、8和13中的find需要修改代码,除非将输入参数解析为表变量)


下面是一个使用非相关子查询和无
分组依据的解决方案:

SELECT column1, column2 
FROM sets 
WHERE id IN (
  SELECT g1.set_id FROM set_has_group g1
  JOIN set_has_group g2 ON (g1.set_id = g3.set_id)
  JOIN set_has_group g3 ON (g1.set_id = g3.set_id)
  WHERE g1.group_id = 1 AND g2.group_id = 2 AND g3.group_id = 3);

集合是组的集合,还是组的集合,或者两个集合都是彼此的集合?您的命名有点混乱。集合是主要的数据模型,它们可能被“标记”为属于几个组。我正在尝试查找属于组1、2和3的集合
SELECT column1, column2 
FROM sets 
WHERE id IN (
  SELECT g1.set_id FROM set_has_group g1
  JOIN set_has_group g2 ON (g1.set_id = g3.set_id)
  JOIN set_has_group g3 ON (g1.set_id = g3.set_id)
  WHERE g1.group_id = 1 AND g2.group_id = 2 AND g3.group_id = 3);