繁体   English   中英

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

[英]Select Records that match ALL groups in a many to many join table

我有2个表:集合和组。 两者都使用第三个表set_has_groups连接。 我想获取具有我指定的所有组的集合

一种方法是

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         
)

真的非常快它与第二个查询相同,只是我将其包装在另一个临时表中

我怀疑在第二个查询中有一个小问题。

真的,我不确定。 可能第二个查询是通过全表扫描执行的。 同时,第一个“ IN”实际上转换为“ 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,这是一个带有JOIN的工作示例,只要正确设置了主键和外键,JOIN的性能就会比您正在使用的IN子句更好。 我已经建立了将5组加入3组的组,但是组4和5不是组3的一部分,因此不会显示在答案中。 但是,此查询不可扩展(例如,在第4、5、7、8和13组中的查找将需要修改代码,除非您将输入参数解析为表变量)

set nocount on

declare @sets table
(
Id  INT Identity (1, 1),
Column1 VarChar (50),
Column2 VarChar (50)
)

declare @Set_Has_Group table
(
    Set_Id  Int,
    Group_Id    Int
)

insert into @sets values (newid(), newid())
insert into @sets values (newid(), newid())
insert into @sets values (newid(), newid())
insert into @sets values (newid(), newid())
insert into @sets values (newid(), newid())

update @sets set column1 = 'Column1 at Row ' + Convert (varchar, id)
update @sets set column2 = 'Column2 at Row ' + Convert (varchar, id)

insert into @Set_Has_Group values (1, 1)
insert into @Set_Has_Group values (1, 2)
insert into @Set_Has_Group values (1, 3)
insert into @Set_Has_Group values (2, 1)
insert into @Set_Has_Group values (2, 2)
insert into @Set_Has_Group values (2, 3)
insert into @Set_Has_Group values (3, 1)
insert into @Set_Has_Group values (3, 2)
insert into @Set_Has_Group values (3, 3)
insert into @Set_Has_Group values (4, 1)
insert into @Set_Has_Group values (4, 2)
insert into @Set_Has_Group values (5, 1)
insert into @Set_Has_Group values (5, 2)

/* your query with IN */
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)

/* my query with JOIN */
SELECT * -- Column1, Column2
FROM    @sets sets
WHERE 3 = (
    SELECT Count (1)
    FROM @Set_Has_Group Set_Has_Group
    WHERE 1=1
        AND sets.Id = Set_Has_Group.Set_Id
        AND Set_Has_Group.Group_ID IN (1, 2, 3)
    Group by Set_Id
    )

这是一个使用不相关子查询且不使用GROUP BY的解决方案:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM