SQL选择where作为交集而不是union

时间:2018-02-21 15:41:27

标签: sql sql-server database

我将通过示例解释问题,因此在给定以下数据结构的情况下很容易理解:

id  userId  
1   1    
1   2    
2   2    
3   2    
1   3     
2   3 

我可以为一组用户获取id的列表,如下所示:

declare @tmp table (id int, userId int)
insert into @tmp values(1,1), (1,2), (2,2), (3,2), (1,3), (2,3)


select id from @tmp
where userId in (1,2,3)
group by id

这将按预期返回以下内容:

id
1
2
3

我的问题是,我怎样才能获得在where子句中为 EVERY userId映射的ID?例如userId in (1,2,3)的结果应为1userId in (2,3)的结果应为1,2

我已尝试浏览每个ID然后合并这些但到目前为止没有找到实际解决方案的运气。

注意解决方案必须适用于更大的数据集,想象数百万行和数千个userIds,解决方案的效率并不重要(因为它不必经常运行)

第二次注意我刚刚注意到计算结果实际上并不能保证正确性,因为两个不同的userId可能具有相同的映射计数但映射到不同的项目。在那种情况下,它不再是一个交叉点

4 个答案:

答案 0 :(得分:1)

我使用临时表来存储用户ID

declare @tmp table (id int, userId int)
insert into @tmp values(1,1), (1,2), (2,2), (3,2), (1,3), (2,3)

declare @userid table (id int)
insert into @userid values (1), (2), (3)

select
    t.id
from 
    (select *, cnt = count(*) over () from @userid) u
    join @tmp t on u.id = t.userId
group by t.id, u.cnt
having u.cnt = count(distinct u.id)

答案 1 :(得分:1)

如果您唯一的问题是您只想指定一次用户ID,请使用您的用户表:

with u as (select userid from users where userid in (1,2,3))
select id 
from mytable
where userid in (select userid from u)
group by id
having count(distinct userid) = (select count(*) from u);

如果您想对无效的用户ID做出反应,结果为空,那么您可以使用values子句替换users表:

with u as (select userid from (values (1), (2), (3)) AS ids(userid))

答案 2 :(得分:1)

您可以避免count distinct以及不止一次输入userId值 - 或者如果您从动态查询中填充@i数据集的等效值,则可以避免:

declare @t table (id int, userId int);
insert into @t values(1,1), (1,2), (2,2), (3,2), (1,3), (2,3);

declare @i table (i int);
insert into @i values(1),(2),(3);

select t.id
from @i as i
    join @t as t
        on i.i = t.userId
group by t.id
having count(i.i) = (select count(1) from @i);

答案 3 :(得分:0)

一种方法是使用HAVING

SELECT id
FROM YourTable
GROUP BY id
HAVING COUNT(CASE WHEN UserID = 1 THEN 1 END) > 0
   AND COUNT(CASE WHEN UserID = 2 THEN 1 END) > 0
   AND COUNT(CASE WHEN UserID = 3 THEN 1 END) > 0;