查找仅存在 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');
我有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');