查找仅存在 2 个值的记录

find a records which exists for 2 values only

我有Table structure/Data设置是这样的

Emp_id  Expense_amt_dollar  Dept
1111    100                 Marketing    
1111    75                  Finance
1111    25                  IT
2222    100                 Marketing
3333    50                  Finance
4444    30                  Marketing
4444    70                  Finance
5555    200                 IT

O/P 我只在 2 个部门寻找 Emp 费用

Emp_id  Expense_amt_dollar  Dept
1111    100                 Marketing
1111    75                  Finance
4444    30                  Marketing
4444    70                  Finance

只有这两个部门的记录的Emp。 两个部门的记录都应该有。

EXISTS:

select t.* from tablename t
where t.dept in ('Finance', 'Marketing')
and exists (
  select 1 from tablename
  where emp_id = t.emp_id and dept in ('Finance', 'Marketing') and dept <> t.dept
)

或具有 CTE:

with cte as (
  select t.* from tablename t
  where t.dept in ('Finance', 'Marketing')
)
select c.* from cte c
where exists (
  select 1 from cte 
  where emp_id = c.emp_id and dept <> c.dept
)

参见demo
结果:

> EMP_ID | EXPENSE_AMT_DOLLAR | DEPT     
> -----: | -----------------: | :--------
>   1111 |                 75 | Finance  
>   1111 |                100 | Marketing
>   4444 |                 70 | Finance  
>   4444 |                 30 | Marketing

您可以 select 营销和财务行,然后检查您是否为员工同时获得了这两个行:

select *
from
(
  select emp_id, dept, count(*) over (partition by emp_id) as cnt
  from mytable t
  where dept in ('Marketing', 'Finance')
)
where cnt = 2
order by emp_id, dept;

Emp which having records for these 2 dept only. Records should have for both dept.

我会使用 window 函数:

select emp_id, expense_amt_dollar, dept
from (
    select 
        e.*, 
        sum(case when dept in ('Marketing', 'Finance') then 1 end) over(partition by emp_id) cnt_deps
        sum(case when dept not in ('Marketing', 'Finance') then 1 end) over(partition by emp_id) cnt_other_deps
    from emp e
) e
where cnt_deps = 2 an cnt_other_deps is null

这为您提供了属于两个部门 的员工的记录,而不属于其他部门 - 这就是我对您的问题的理解。为此,您需要查看整个 table:使用 where 子句进行过滤会阻止您检查该员工是否不属于任何其他部门。

另一种选择是使用 having count(distinct dept) = 2 子句生成子查询,然后使用相同的 table.

进行连接
select t1.*
  from tab t1
  join (select emp_id, max(dept) dept1, min(dept) dept2
          from tab
         where dept in ('Finance', 'Marketing')
         group by emp_id
        having count(distinct dept) = 2) t2
    on t1.emp_id = t2.emp_id
   and t1.dept in (t2.dept1, t2.dept2)

曾在 Postgresql 工作过:

select * 
from employee_expenses
where emp_id in 
(
select emp_id from employee_expenses 
where dept = 'Finance'
intersect
select emp_id from employee_expenses
where dept ='Marketing'
)
and dept in ('Finance', 'Marketing');