我有2个表:集合和组。两者都使用第3个表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
)
真的很快 它与第二个查询相同,只是我将它包装在另一个临时表中 很奇怪
答案 0 :(得分:1)
我怀疑第二个查询中有一个小错误。
真的,我不确定。可能,第二个查询是通过全表扫描执行的。与此同时,第一个“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)
答案 1 :(得分:0)
假设SQL Server,这里有一个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
)
答案 2 :(得分:0)
这是一个使用非相关子查询但没有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);