多表联查(多表连接)(join)
1、 分类
内连接、自然连接、外链接(左外连接、右外连接、全外连接(mysql不支持))
2、 内连接 inner join(等值连接,制定对应的等值条件)
SELECT * FROM emp,dept;/*得到的数据是不对的*/
得到的数据叫做笛卡尔积:结果是两个表数据的乘积
使用内连接去查
SELECT * FROM emp INNER JOIN dept;
结果依然是笛卡尔积,是因为我们没有制定对应的等值条件
SELECT * FROM emp e INNER JOIN dept d WHERE e.deptno = d.deptno;
/*emp.deptno和dept.deptno这样的写法叫做:完全限定名
两个表中有相同的字段,类似于A村有个老张家,孩子叫张三
B村也有一个老张家,孩子也叫张三,
如果没有用到多表联查,就没有必要使用完全限定名,类似于
A村老张家的爸爸说,张三,吃饭了,指的是自己的孩子
用到了夺标联查,两家在一起,A村的老张家的爸爸说:张三,吃饭了
这个张三指的是谁?(不一定)
*/
提示:一般来讲,我们不使用内连接,因为效率低。用外链接
标准写法:select * from 表1 别名1 inner join 表2 别名2 where 别名1.xxx = 别名2.xxx;
SELECT * FROM emp e INNER JOIN dept d WHERE e.deptno = d.deptno;
方言写法:select * from 表1 别名1,表2别名2 where别名1.xxx = 别名2.xxx;
SELECT * FROM emp e,dept d WHERE e.deptno = d.deptno;
3、 自然连接 natural(不需要指定等值条件)
select * from 表1 别名1 natural join 表2 别名2;
4、 外链接(难点)
左外:select * from 表1 别名1 left [ outer ] join 表2 别名2 on 等值条件;
SELECT * FROM emp e LEFT OUTER JOIN dept d ON e.deptno = d.deptno;
左外的意思是:左表的记录无论是否满足条件,都会被查出来,而右表的记录只有满足条件的,才会被查出来。(左表中数据在右表中如果不存在,则右表的字段值为null)
理解左外右外:
先看两个表数据:
/*左外*/
SELECT * FROM table1 t1 LEFT JOIN table2 t2 ON t1.id = t2.id;
左外连接是以左边的表为基准。通俗的讲,先把左表的数据全都显示出来,然后右边的表id与左边表的id的值是一样的,就拼接上去,比如说上面的id=1的数据,就拼接了。
如果没有匹配的,比如说id=2的数据,右边没有,用null拼接。
/*右外 */
SELECT * FROM table1 t1 RIGHT JOIN table2 t2 ON t1.id = t2.id;
右外跟左外的机制刚好相反。
如何去判断主副表?(左外连接:左边的是主表,右外连接:右边的是主表)
跟讲过的内连接做个简单的比较
SELECT * FROM table1 t1,table2 t2 WHERE t1.id = t2.id;
区别:内连接显示的是满足等值条件的记录,而外链接主表的记录都显示出来。
注意:使用多表联查,不一定要有外键。
例题:/*查询所有工作为文员的员工姓名及部门名称*/
SELECT e.ename,e.job,d.dname
FROM emp e LEFT JOIN dept d ON e.deptno = d.deptno
WHERE e.job = '文员';
例题:/*查询至少有一个员工的部门信息*/
结果很显然不对,因为40部门没人。
分析:因为我把dept作为主表,而主表的数据都显示,所以不合适,更改如下:
如下写法也可以
其实可以不用外链接,也可以查询
子查询
子查询:查询中还有查询(数select的个数)
1、 出现的位置
A from前:作为字段存在的
B where后:作为条件存在的
/*查询出工资高于在30部门工作的所有员工的工资的员工信息*/
C from后:表(极为罕见)