我正在尝试转换以下查询:
select *
from employees
where emp_id not in (select distinct emp_id from managers);
到我将子查询表示为连接的表单中。我试过了:
select *
from employees a, (select distinct emp_id from managers) b
where a.emp_id!=b.emp_id;
我也尝试过:
select *
from employees a, (select distinct emp_id from managers) b
where a.emp_id not in b.emp_id;
但它没有给出相同的结果。我已经尝试了“内部加入”#39;语法也是如此,但无济于事。我对这个看似简单的问题感到沮丧。任何帮助将不胜感激。
答案 0 :(得分:2)
假设员工数据集
Emp_ID
1
2
3
4
5
6
7
假设Manger数据集
Emp_ID
1
2
3
4
5
8
9
select *
from employees
where emp_id not in (select distinct emp_id from managers);
上面没有加入表格所以没有生成笛卡尔积...你只有7条记录...
以上会导致6和7为什么?员工数据中只有6和7不在经理表中。管理员中的8,9被忽略,因为您只返回员工的数据。
select *
from employees a, (select distinct emp_id from managers) b
where a.emp_id!=b.emp_id;
以上没有工作,因为生成了笛卡尔积...所有员工都是经理(假设每张表中7条记录7 * 7 = 49) 所以不要像在第一个查询中一样评估员工数据。现在,您还要评估所有员工的所有经理
所以选择*结果
1,1
1,2
1,3
1,4
1,5
1,8
1,9
2,1
2,2...
更少where子句匹配... 所以7 * 7-7或42.虽然这可能是生命世界及其中所有东西的答案,但这不是你想要的。
我也尝试过:
select *
from employees a, (select distinct emp_id from managers) b
where a.emp_id not in b.emp_id;
再一次笛卡尔......所有员工都是所有经理
所以这就是左连接工作的原因
SELECT e.*
FROM employees e
LEFT OUTER JOIN managers m
on e.emp_id = m.emp_id
WHERE m.emp_id is null
这首先表示加入ID ...所以不要生成笛卡尔,而是实际加入一个值来限制结果。但由于它是LEFT连接,因此从LEFT表(员工)返回一切,只返回与经理匹配的那些。
因此在我们的示例中将返回为e.emp_Di = m.Emp_ID
1,1
2,2
3,3
4,4
5,5
6,NULL
7,NULL
现在是where子句所以
6,Null
7,NULL are retained...
旧的ansii左连接的SQL标准在where子句中是* =
select *
from employees a, managers b
where a.emp_id *= b.emp_id --I never remember if the * is the LEFT so it may be =*
and b.emp_ID is null;
但是我发现这种符号更难以阅读,因为联接可以与其他限制标准混在一起......
答案 1 :(得分:1)
试试这个:
select e.*
from employees e
left join managers m on e.emp_id = m.emp_id
where m.emp_id is null
这将加入两个表。然后我们丢弃我们找到匹配经理的所有行,并留下不是经理的员工。
答案 2 :(得分:1)
使用Left Outer Join
代替
select e.*
from employees e
left outer join managers m
on e.emp_id = m.emp_id
where m.emp_id is null
左外连接将保留m
表中的行,即使它们没有基于e
字段的匹配i emp_id
表。我们在where m.emp_id is null
上过滤 - 给我e
中m
表中没有匹配记录的所有行。
关于这个问题的更多内容可以在这里找到:
Visual representation of joins
from employees a, (select distinct emp_id from managers) b
隐含cross join
- 表之间的所有可能组合(而您需要left outer join
)
答案 3 :(得分:1)
你最好的选择可能是左联盟:
select
e.*
from employees e
left join managers m on e.emp_id = m.emp_id
where
m.emp_id is null;
这里的想法是你要说你要从员工中选择所有内容,包括基于emp_id在管理器表中匹配的所有内容,然后过滤出实际上在manager表中有某些内容的行。
答案 4 :(得分:0)
MINUS
关键字应该可以解决问题:
SELECT e.* FROM employees e
MINUS
Select m.* FROM managers m
希望有帮助...
答案 5 :(得分:0)
select *
from employees
where Not (emp_id in (select distinct emp_id from managers));