数据库基础2

多表查询

#显示雇员名,雇员工资及所在部门的名字
#雇员名,雇员工资来自 emp表
#部门的名字来自 dept 表
#当我们需要指定某个表的列:表.列名
SELECT ename,sal,dname
	FROM emp,dept
	WHERE emp.deptno = dept.deptno
#显示员工姓名,工资,工资级别

#姓名,工资来自emp 工资级别来自salgrade

SELECT ename,sal,grade
	FROM emp,salgrade
	WHERE sal BETWEEN losal AND hisal;
	

自连接

自连接是指在同一张表的连接查询

#显示公司员工名字和他上级的名字
#员工名字在emp表中,上级的名字也在emp中,两者通过emp中的mgr列关联

SELECT worker.ename AS '职员名', boss.ename AS '上级名'
	FROM emp worker, emp boss
	WHERE worker.mgr = boss.empno #职员上司的编号
	
#自连接的特点:1. 把同一张表当作两张表使用
#		2. 需要给表取别名(一个worker表,一个boss表)

子查询

子查询是指嵌入在其它sql语句中的select语句,也叫嵌套查询

单行子查询

指只返回一行数据的子查询语句 使用 =

#如何显示与smith在同一部门的所有员工

#1. 先查询到smith的部门号
#2. 把上面的select语句当作一个子查询来使用

SELECT deptno
	FROM emp
	WHERE ename = 'smith';
	
SELECT * 
	FROM emp
	WHERE depto = (
		SELECT deptno
		FROM emp
		WHERE ename = 'smith'
	)

多行子查询

返回多行数据的子查询,使用关键字 in 

#查询和部门10工作内容相同的员工的 名字、岗位、工资、部门号
#但是不包括部门10的员工

# 1. 查询到10号部门有哪些工作 (不能重复,因此用distinct)
# 2. 把上面查询的结果当作子查询使用

SELECT DISTINCT job
	FROM emp
	WHERE deptno = 10;
	
SELECT ename,job,sal,deptno
	FROM emp
	WHERE job IN (
		SELECT DISTINCT job
		FROM emp
		WHERE deptno = 10
	) AND deptno != 10  #部门不为10

子查询临时表

可以将子查询当作一张临时表使用

#查询ecshop中各个类别,价格最高的商品

#先得到各个类别中,价格最高的商品 (max, group by cat_id) 当作临时表

SELECT cat_id,MAX(shop_price)
	FROM ecshop
	GROUP BY cat_id
#获得编号+对应的最高价格	

SELECT goods_id,ecshop.cat_id,goods_name,shop_price #注意要声明哪个表中的cat_id
	FROM (
		SELECT cat_id,MAX(shop_price)
		FROM ecshop
		GROUP BY cat_id
	) temp , ecshop #temp是临时表的名字,从临时表和总表中查找
	WHERE temp.cat_id = ecshop.cat_id
	AND temp.max_pricr = ecshop.shop_price
#满足编号相同,价格是最大的,输出信息

all 和 any

#显示工资比部门30 的所有员工的工资高 的员工的姓名、工资和部门号

SELECT ename,sal,deptno
	FROM emp
	WHERE sal > ALL(
		SELECT sal
		FROM EMP
		WHERE deptno = 30
	) #嵌套查询 ,查出所有部门30员工的工资
	
#注:也可以把ALL 改成 MAX
#显示工资比部门30 的其中一个工资高 的员工的姓名、工资和部门号

SELECT ename,sal,deptno
	FROM emp
	WHERE sal > ANY(
		SELECT sal
		FROM EMP
		WHERE deptno = 30
	) #嵌套查询 ,查出所有部门30员工的工资
	
#注:也可以把ANY 改成 MIN

基本上ALL等价于MAX,ANY等价于MIN。

多列子查询

WHERE (字段1,字段2...) = (子查询语句)

#多列子查询返回多个列数据

#查询与smith部门和岗位完全相同的所有雇员(不包括smith本人)
SELECT deptno , job
	FROM emp
	WHERE ename = 'smith'  #得到smith的岗位和工作
	
#把上面的查询当作子查询来使用,并且使用多列子查询的语法来匹配
SELECT * 
	FROM emp
	WHERE (deptno,job) = (
		SELECT deptno , job
		FROM emp
		WHERE ename = 'smith' 
	) AND ename != 'smith'

一些练习

#查找每个部门工资高于本部门平均工资的人的资料

#1.先得到每个部门的部门号和对应的平均工资
SELECT deptno,AVG(sal) AS avg_sal
	FROM emp
	GROUP BY deptno  #用部门号进行分组
	
#2. 把上面的结果当作子查询,和emp进行多表查询

SELECT ename,sal,temp.avg_sal,emp.deptno
	FROM emp,(
		SELECT deptno,AVG(sal) AS avg_sal
		FROM emp
		GROUP BY deptno
	)temp
	WHERE emp.deptno = temp.deptno AND emp.sal > temp.avg_sal
#查询每个部门的信息和人员数量

#部门信息在dept表(部门名,编号,地址)
#各个部门的人员数量 -> 构建一个临时表

SELECT COUNT(*),deptno
	FROM emp
	GROUP BY deptno

SELECT dname,dept.deptno,loc,tmp.per_num AS '人数' 
    #也可以把 deptno和per_num 合并写成 tmp.*
	FROM dept, (
		SELECT COUNT(*),deptno
		FROM emp
		GROUP BY deptno
	) tmp
	WHERE dept.deptno = tmp.deptno

注:在多表查询中,当多个表的列不重复时,才可以直接写列名。

表复制

#把emp表复制到my_tab01中

INSERT INTO my_tab01
	(id,`name`,sal,job,deptno)
	SELECT empno,ename,sal,job,deptno 
	FROM emp
#自我复制
INSERT INTO my_tab01
	SELECT * FROM mytab_01

表去重

#创建一个临时表和要去重的表结构相同
CREATE TABLE my_tmp LIKE my_tab02 

#把tab02的记录通过distinct处理后 复制到tmp
INSERT INTO my_tmp
	SELECT DISTINCT * FROM my_tab02
	
#清除掉tab02的记录
DELETE FROM my_tab02

#把tmp表的记录复制到tab02
INSERT INTO my_tab02
	SELECT * FROM my_tmp
	
#drop掉临时表tmp
DROP TABLE my_tmp;

合并查询

SELECT ename,sal,job FROM emp WHERE sal >2500
UNION ALL  #查询结果合并,不会去重   DISTINCT会去重
SELECT ename,sal,job FROM emp WHERE job = 'MANAGER'

外连接

        列出部门名称和这些部门的员工名称和工作,同时要求 显示出那些没有员工的部门,这个无法用多表查询得到(因为无法关联起来)

#使用左外连接实现
SELECT dname,ename,job
	FROM dept LEFT JOIN emp
	ON dept.deptno = emp.deptno
	
#使用右外连接实现
SELECT dname,ename,job
	FROM emp RIGHT JOIN dept
	ON dept.deptno = emp.deptno

mysql约束

primary key(主键)

CREATE TABLE t17
	(id INT PRIMARY KEY, #表示id列是主键,主键列的值不可以重复,并且不能是NULL
	...
	);

注:1. 一张表最多有一个主键,但可以是复合主键

CREATE TABLE t17
	(id INT, 
	`name` VARCHAR(32) 
	PRIMARY KEY(id,`name`) #复合主键,只有id和name都重复时才报错,只有一个重复不报错
	);

2. 主键指定方式有两种:A. 直接在字段名后指定  B. 在表定义的最后写

3. 使用 desc 表名,可以看到primary key 的情况
 

unique

加上unique后,值不能重复

1. 如果没有指定not null,那么unique字段可以有多个null

2. 如果指定了 not null,那么使用效果类似于 primary key

3. 一张表可以有多个unique字段

CREATE TABLE t17
	(id INT UNIQUE,
	`name` VARCHAR(32) 
	);

外键

#创建主表
CREATE TABLE my_class(
	id INT PRIMARY KEY,
	`name` VARCHAR(32) NOT NULL DEFAULT '');

#创建从表
CREATE TABLE my_stu(
	id INT PRIMARY KEY,
	`name` VARCHAR(32) NOT NULL DEFAULT '',
	class_id INT,
	#下面指定外键关系
	FOREIGN KEY(calss_id) REFERENCES my_class(id))

   比如主表里有class 3,但是从表还没有class 3的学生。这时候可以删除主表的class 3。如果有,就不能删除了。 

check

CREATE TABLE t23(
	id INT PRIMARY KEY,
	`name` VARCHAR(32),
	sex VARCHAR(6) CHECK(sex IN('man','woman')),
	sal DOUBLE CHECK (sal >10 AND sal<2000)
	);

自增长

        添加后,该字段从1开始自增长

CREATE TABLE t24(
	id INT PRIMARY KEY AUTO_INCREMENT);
#修改默认的自增长开始值
ALTER TABLE t24 AUTO_INCREMENT = 100

 比如加入了500这个数值,那么下一次就从501开始。

索引

原理就是二叉搜索树。

#在emp表的 empno列创建索引

CREATE INDEX empno_index ON emp(empno)

添加索引 

#查询表是否有索引
SHOW INDEXES FROM t25;

#添加唯一索引
CREATE UNIQUE INDEX id_index ON t25(id);

#添加普通索引
CREATE INDEX id_index ON t25(id);
ALTER TABLE t25 ADD INDEX id_index(id);
#如何选择:
#	如果某列的值是不会重复的,那么优先考虑使用unique索引,否则使用普通索引

#添加主键索引
CREATE TABLE t26(
	id INT,
	`name` VARCHAR(32));
	
ALTER TABLE t26 ADD PRIMARY KEY(id); #这个跟直接在CREATE写primary key效果相同

删除索引 

#删除索引
DROP INDEX id_index ON t25
#删除主键索引
ALTER TABLE t26 DROP PRIMARY KEY

#修改索引:先删除,再添加新的索引

查询索引

SHOW INDEX FROM t25

什么时候使用索引 

第四条:也就是该字段用不到select。 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值