MySQL——多表查询

创建外键:在创建表的时候建立

CREATE TABLE emp_mul(
eid VARCHAR(20) PRIMARY KEY COMMENT "员工编号",
ename VARCHAR(20) COMMENT "员工名字",
age INT COMMENT "年龄", 
dept_id VARCHAR(20) COMMENT "部门编号",
CONSTRAINT emp_fk FOREIGN KEY (dept_id) REFERENCES dept_mul(deptno));

#CONSTRAINT emp_fk FOREIGN KEY (dept_id) REFERENCES dept_mul(deptno))创建外表的关键语句,创建名称为emp_fk,该主键依附于dept_mul的deptno字段。

创建主键:建立表之后建立外键

#假设已建立主表student_mul和从表score,则创建名称为student_fk的外键,score表的sid依附于student_mul的sid;

ALTER TABLE score ADD CONSTRAINT student_fk FOREIGN KEY(sid) REFERENCES student_mul(sid);

多表查询案例:

1.数据准备

##主表
CREATE TABLE dept (
id INT PRIMARY KEY auto_increment COMMENT"ID",
name VARCHAR(50) NOT NULL COMMENT "部门名称") COMMENT "部门表";
INSERT INTO dept (name) VALUES ('研发部'), ('市场部'),('财务部'), ('销售部'), ('总经办'), ('人事部');
##从表
create table emp(
id int primary key auto_increment comment 'ID',
name varchar(50) not null comment '姓名',
age int comment '年龄',
job varchar(20) comment '职位',
salary int comment '薪资',
entrydate date comment '入职时间',
managerid int comment '直属领导ID',
dept_id int comment '部门ID'
) comment '员工表';
#'直属领导ID'受到id列的影响,foregin KEY managerid REFERENCES (id) 
##添加外键
ALTER TABLE emp ADD CONSTRAINT fk_dept_id FOREIGN KEY(dept_id) REFERENCES dept(id);
INSERT INTO emp (id, name, age, job,salary, entrydate,managerid, dept_id) VALUES
(1, '金庸', 66, '总裁',20000, '2000-01-01', null,5),
(2, '张无忌', 20, '项目经理',12500, '2005-12-05', 1,1),
(3, '杨逍', 33, '开发', 8400,'2000-11-03', 2,1),
(4, '韦一笑', 48, '开发',11000, '2002-02-05', 2,1),
(5, '常遇春', 43, '开发',10500, '2004-09-07', 3,1),
(6, '小昭', 19, '程序员鼓励师',6600, '2004-10-12', 2,1),
(7, '灭绝', 60, '财务总监',8500, '2002-09-12', 1,3),
(8, '周芷若', 19, '会计',48000, '2006-06-02', 7,3),
(9, '丁敏君', 23, '出纳',5250, '2009-05-13', 7,3),
(10, '赵敏', 20, '市场部总监',12500, '2004-10-12', 1,2),
(11, '鹿杖客', 56, '职员',3750, '2006-10-03', 10,2),
(12, '鹤笔翁', 19, '职员',3750, '2007-05-09', 10,2),
(13, '方东白', 19, '职员',5500, '2009-02-12', 10,2),
(14, '张三丰', 88, '销售总监',14000, '2004-10-12', 1,4),
(15, '俞莲舟', 38, '销售',4600, '2004-10-12', 14,4),
(16, '宋远桥', 40, '销售',4600, '2004-10-12', 14,4),
(17, '陈友谅', 42, null,2000, '2011-10-12', 1,null);

dept表:

emp表:

2.案例

2.1交叉查询

SELECT * FROM emp,dept

一般不常用,只是作为查询的一个过程,计算的是笛卡儿积:产生冗余数据,若表1有16条数据,表2有7条数据,则结果数据存在16×7条数据。

2.2 内连接

内连接:WHERE

#模板
SELECT 字段列表 FROM 表1 , 表2 WHERE 条件 ... ;

内连接:嵌入式内连接:JOIN ON

#模版:
SELECT 字段列表 FROM 表1 [ INNER ] JOIN 表2 ON 连接条件 ... ;

例:查询每个员工的姓名,及关联的部门名称

#方法一:隐式内连接 :WHERE
SELECT emp.name as "姓名",dept.name as "部门名称" FROM emp,dept WHERE emp.dept_id=dept.id

#方法二:嵌入式内连接:JOIN ON
SELECT e.id,e.name as "姓名",d.name as "部门名称" FROM emp e JOIN dept d ON e.dept_id=d.id ORDER BY e.id;

2.3外连接

左外连接:LEFT JOIN ON(更倾向于用)

#模版:
SELECT 字段列表 FROM 表1 LEFT [ OUTER ] JOIN 表2 ON 条件 ... ;

以左表的数据为基础,结合左表和右表的交集,右表无对应的则返回null。

右外连接:RIGHT JOIN ON

#模版:
SELECT 字段列表 FROM 表1 RIGHT [ OUTER ] JOIN 表2 ON 条件 ... ;

与左外连接相反

满外连接:full outer join 。MySQL不支持,oracle支持

例子:查询emp表的所有数据, 和对应的部门信息

#右外连接:RIGHT JOIN ON
SELECT emp.*,dept.name as "dept_name" FROM dept RIGHT JOIN emp ON emp.dept_id=dept.id order by id;
##自连接(join on)
#查询员工及其所属领导的名字
SELECT a.name "员工名字",b.name "领导名字" FROM emp a ,emp b WHERE a.id=b.managerid;

2.3自连接

①自己连接自己,将一张表作为多张表进行查询;②自连接的时候一定要取别名

自连接查询

#模版
SELECT 字段列表 FROM 表A 别名A JOIN 表A 别名B ON 条件 ... ;

自连接查询的时候也可以是内连接查询也可以是外面接查询

例子:查询员工 及其 所属领导的名字

select a.name , b.name from emp a , emp b where a.managerid = b.id;

联合查询:利用union 将查询结果拼在一起,上下拼接。

#模板
SELECT 字段列表 FROM 表A ...
UNION [ ALL ]
SELECT 字段列表 FROM 表B ....;

注:union与union all的区别:union并未去重,union all是去重之后的数据。

例子:将薪资低于 5000 的员工 , 和 年龄大于 50 岁的员工全部查询出来。

select * from emp where salary < 5000
union all
select * from emp where age > 50;

2.4子查询

就是嵌套select

#模板
SELECT * FROM t1 WHERE column1 = ( SELECT column1 FROM t2 ); 1

例子:子查询为单行单列,运算符为= ,<, <=,>,>=

查询年龄最大的员工

SELECT * 
FROM emp
WHERE age=(SELECT max(age) FROM emp);

例子:子查询为多行单列。运算符有IN,NOT IN,ANY,SOME,ALL(any与some的结果一致),any,all 要与运算符= ,<, <=,>,>=一起使用

查询研发部和销售部的员工信息

SELECT * from emp 
WHERE dept_id in(SELECT id FROM dept WHERE name="研发部" or name="销售部");

例子:子查询为单行多列,操作符:= ,<>,IN,NOT IN

查询与张无忌薪资及直属领导相同的员工信息

SELECT * FROM emp WHERE (salary,managerid)=(SELECT salary,managerid FROM emp WHERE name="张无忌");

例子:子查询为多行多列,操作符IN

查询 "鹿杖客" , "宋远桥" 的职位和薪资相同的员工信息

SELECT * FROM emp WHERE (job,salary) in (SELECT job,salary FROM emp WHERE name='鹿杖客' or name="宋远桥");

补充关键词:where EXISTS(查询语句),如果exists()返回true,则行使子查询,否则不执行,exists查询效率更高
查询公司里大于60岁的员工

SELECT * FROM emp e WHERE EXISTS(SELECT * FROM emp where e.age>60);

练习:

1.查询所有的部门信息,并统计部门的员工人数

2.查询低于本部门平均薪资的员工信息

SELECT new_table.dept_id,dept.name FROM(
SELECT dept_id,count(*) FROM emp GROUP BY dept_id) as new_table
join dept on new_table.dept_id=dept.id;

select * from emp e2 where e2.salary < ( select avg(e1.salary) from emp e1 where
e1.dept_id = e2.dept_id );

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值