Select users belonging only to particular departments

后端 未结 12 2113
挽巷
挽巷 2021-02-18 12:49

I have the following table with two fields namely a and b as shown below:

create table employe
(
    empID varchar(10),
    department varchar(10)
);


        
相关标签:
12条回答
  • 2021-02-18 13:31

    I know that this question has already been answered, but it was a fun problem to do and I tried to do it in a way that no one else has. Benefits of mine is that you can input any list of strings as long as each value has a comma afterwards and you don't have to worry about checking counts.

    Note: Values must be listed in alphabetic order.

    XML Solution with CROSS APPLY

    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,'
    

    Results:

    empID
    ----------
    A103
    
    0 讨论(0)
  • 2021-02-18 13:34

    This is a Relational Division with no Remainder (RDNR) problem. See this article by Dwain Camps that provides many solution to this kind of problem.

    First Solution

    SQL Fiddle

    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
        )
    

    Second Solution

    SQL Fiddle

    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)
    

    Without using GROUP BY and HAVING:

    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
        )
    
    0 讨论(0)
  • 2021-02-18 13:34

    What about a self join? (ANSI Compliant - worked for 20+ years)

    SELECT * FROM employee e JOIN employee e2 ON e.empid = e2.empid
    WHERE e.department = 'x' AND e2.department ='y'
    

    This shows that a101 and a104 both work in both departments.

    0 讨论(0)
  • 2021-02-18 13:36

    Solution using where clause:

    select distinct e.empID
    from employe e
    where exists( select * 
                  from employe
                  where empID = e.empID
                  having count(department) = count(case when department in('Y','X','Z') then department end)
                     and count(distinct department) = 3)
    

    exists checks if there are records for specific EmpId that have total count of departments equal to conditional count of only matching departments and that it is also equal to the number of departments provided to the in clause. Also worth mentioning that here we apply having clause without the group by clause, on the whole set, but with already specified, only one empID.

    SQLFiddle

    You can achieve this without the correlated subquery, but with the group by clause:

    select e.empId
    from employe e
    group by e.empID
    having count(department) = count(case when department in('Y','X','Z') then department end)
       and count(distinct department) = 3
    

    SQLFiddle

    You can also use another variation of having clause for the query above:

    having count(case when department not in('Y','X', 'Z') then department end) = 0
       and count(distinct case when department in('Y','X','Z') then department end) = 3
    

    SQLFiddle

    0 讨论(0)
  • 2021-02-18 13:42

    try this

    select empID from employe 
    where empId in (select empId from employe 
    where department = 'Z' and department = 'Y') 
    and empId not in (select empId from employe 
    where department = 'X') ;
    
    0 讨论(0)
  • 2021-02-18 13:44

    You can use GROUP BY with having like this. SQL Fiddle

    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
    

    Without GROUP BY and Having

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

    If you want to use any of the above query with other tables using a join you can use CTE or a derived table like this.

    ;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
    
    0 讨论(0)
提交回复
热议问题