找出列是否包含每个组的两个不同值

vis*_*hal -2 sql t-sql sql-server relational-division

我想选择满足同一列的两个条件的行.下面是表模式.

安全表

Id  RoleId  CompId  SecurityToken       Accesstype
1   1           10           abc        2
2   1           10           xyz        2
3   12          10           abc        2
4   16          12           abc        2
5   16          12           xyz        2
6   30          13           abc        2
7   1           10           efg        2
8   1           10           lmn        0 
Run Code Online (Sandbox Code Playgroud)

我想要"每个RoleID/CompID组合的所有行,其中accesstype = 2,并且有一行包含securitytoken"abc"和包含SecurityToken"xyz"的行用于该角色/ compID组合"

输出应该是

Id  RoleId  CompId  SecurityToken       Accesstype
1   1           10           abc        2
2   1           10           xyz        2
4   16          12           abc        2
5   16          12           xyz        2
Run Code Online (Sandbox Code Playgroud)

Sal*_*n A 6

我相信以下查询将产生所需的输出:

SELECT *
FROM testdata
WHERE Accesstype = 2
AND SecurityToken IN ('abc', 'xyz')
AND EXISTS (
    SELECT 1
    FROM testdata AS tmp
    WHERE RoleId = testdata.RoleId 
    AND CompId = testdata.CompId
    AND Accesstype = testdata.AccessType
    AND SecurityToken IN ('abc', 'xyz')
    HAVING COUNT(DISTINCT SecurityToken) = 2
)
Run Code Online (Sandbox Code Playgroud)

SQL小提琴

为了消除包含额外安全性令牌(例如efglmn)的集合,请将WHERE和HAVING子句更改为:

    WHERE RoleId = testdata.RoleId 
    AND CompId = testdata.CompId
    AND Accesstype = testdata.AccessType
    HAVING COUNT(DISTINCT SecurityToken) = 2
    AND COUNT(DISTINCT SecurityToken) = COUNT(CASE WHEN SecurityToken IN ('abc', 'xyz') THEN 1 END)
Run Code Online (Sandbox Code Playgroud)