选择仅属于特定部门的用户

MAK*_*MAK 23 sql sql-server postgresql sql-server-2008-r2

我有下表有两个字段,即a和b,如下所示:

create table employe
(
    empID varchar(10),
    department varchar(10)
);
Run Code Online (Sandbox Code Playgroud)

插入一些记录:

insert into employe values('A101','Z'),('A101','X'),('A101','Y'),('A102','Z'),('A102','X'),
             ('A103','Z'),('A103','Y'),('A104','X'),('A104','Y'),('A105','Z'),('A106','X');


select * from employe;
Run Code Online (Sandbox Code Playgroud)
empID   department
------------------
A101    Z
A101    X
A101    Y
A102    Z
A102    X
A103    Z
A103    Y
A104    X
A104    Y
A105    Z
A106    X
Run Code Online (Sandbox Code Playgroud)

注意:现在我想显示仅属于该部门Z且仅属于该部门的员工Y.因此,根据条件,A103应该显示唯一的员工,因为他只属于部门ZY.但员工A101不应该出现,因为他属于Z,X, and Y.

预期成果:

如果条件是:ZY则结果应该是:

empID
------
A103
Run Code Online (Sandbox Code Playgroud)

如果条件是:ZX则结果应该是:

empID
------
A102
Run Code Online (Sandbox Code Playgroud)

如果条件是:Z,X并且Y随后的结果应该是:

empID
------
A101
Run Code Online (Sandbox Code Playgroud)

注意:我只想在where子句中执行它(不想使用group byhaving子句),因为我将在另一个中包含这个where.

Fel*_*tan 24

这是一个没有剩余(RDNR)问题的关系部门.请参阅Dwain Camps的这篇文章,为这类问题提供了许多解决方案.

第一解决方案

SQL小提琴

SELECT empId
FROM (
    SELECT
        empID, cc = COUNT(DISTINCT department)
    FROM employe
    WHERE department IN('Y', 'Z')
    GROUP BY empID
)t
WHERE
    t.cc = 2
    AND t.cc = (
        SELECT COUNT(*)
        FROM employe
        WHERE empID = t.empID
    )
Run Code Online (Sandbox Code Playgroud)

二解决方案

SQL小提琴

SELECT e.empId
FROM employe e
WHERE e.department IN('Y', 'Z')
GROUP BY e.empID
HAVING
    COUNT(e.department) = 2
    AND COUNT(e.department) = (SELECT COUNT(*) FROM employe WHERE empID = e.empId)
Run Code Online (Sandbox Code Playgroud)

不使用GROUP BYHAVING:

SELECT DISTINCT e.empID
FROM employe e
WHERE
    EXISTS(
        SELECT 1 FROM employe WHERE department = 'Z' AND empID = e.empID
    )
    AND EXISTS(     
        SELECT 1 FROM employe WHERE department = 'Y' AND empID = e.empID
    )
    AND NOT EXISTS(
        SELECT 1 FROM employe WHERE department NOT IN('Y', 'Z') AND empID = e.empID
    )
Run Code Online (Sandbox Code Playgroud)


Ste*_*han 7

我知道这个问题已经得到了回答,但这是一个有趣的问题,我尝试以别人没有的方式做到这一点.我的好处是你可以输入任何字符串列表,只要每个值后面都有一个逗号,你不必担心检查计数.

注意:值必须按字母顺序列出.

使用CROSS APPLY的XML解决方案

select DISTINCT empID
FROM employe A
CROSS APPLY
            (
                SELECT department + ','
                FROM employe B
                WHERE A.empID = B.empID
                ORDER BY department
                FOR XML PATH ('')
            ) CA(Deps)
WHERE deps = 'Y,Z,'
Run Code Online (Sandbox Code Playgroud)

结果:

empID
----------
A103
Run Code Online (Sandbox Code Playgroud)


Sim*_*lia 6

条件1:z和y

 select z.empID from (select empID from employe where department = 'z' ) as z
inner join (select empID from employe where department = 'y' )  as y 
on z.empID = y.empID
where z.empID Not in(select empID from employe where department = 'x' ) 
Run Code Online (Sandbox Code Playgroud)

条件1:z和x

select z.empID from (select empID from employe where department = 'z' ) as z
inner join (select empID from employe where department = 'x' )  as x 
on z.empID = x.empID
where z.empID Not in(select empID from employe where department = 'y' )
Run Code Online (Sandbox Code Playgroud)

条件1:z,y和x

select z.empID from (select empID from employe where department = 'z' ) as z
inner join (select empID from employe where department = 'x' )  as x 
on z.empID = x.empID
inner join (select empID from employe where department = 'y' )  as y on 
y.empID=Z.empID
Run Code Online (Sandbox Code Playgroud)


ugh*_*hai 5

你可以用GROUP BYhaving这样的.SQL小提琴

SELECT empID 
FROM employe
GROUP BY empID
HAVING SUM(CASE WHEN department= 'Y' THEN 1 ELSE 0 END) > 0
AND SUM(CASE WHEN department= 'Z' THEN 1 ELSE 0 END) > 0
AND SUM(CASE WHEN department NOT IN('Y','Z') THEN 1 ELSE 0 END) = 0
Run Code Online (Sandbox Code Playgroud)

没有GROUP BYHaving

SELECT empID 
FROM employe E1
WHERE (SELECT COUNT(DISTINCT department) FROM employe E2 WHERE E2.empid = E1.empid and  department IN ('Z','Y')) = 2
EXCEPT
SELECT empID 
FROM employe
WHERE department NOT IN ('Z','Y')
Run Code Online (Sandbox Code Playgroud)

如果要使用连接对其他表使用上述任何查询,可以使用CTE或这样的派生表.

;WITH CTE AS 
(

    SELECT empID 
    FROM employe
    GROUP BY empID
    HAVING SUM(CASE WHEN department= 'Y' THEN 1 ELSE 0 END) > 0
    AND SUM(CASE WHEN department= 'Z' THEN 1 ELSE 0 END) > 0
    AND SUM(CASE WHEN department NOT IN('Y','Z') THEN 1 ELSE 0 END) = 0
)
SELECT cols from CTE join othertable on col_cte = col_othertable
Run Code Online (Sandbox Code Playgroud)