MySQL数据库三:DQL语句

1、关于查询结果集的去重?
mysql> select distinct job from emp;  // distinct关键字去除重复记录
+-----------+
| job       |
+-----------+
| CLERK     |
| SALESMAN  |
| MANAGER   |
| ANALYST   |
| PRESIDENT |
+-----------+

mysql> select ename, distinct job from emp;  // 语法错误
以上的sql语句是错误的。

记住:distinct只能出现在所有字段的最前面,distinct后面所有的字段联合起来去重。

mysql> select distinct deptno,job from emp;  // deptno,job联合起来去重
+--------+-----------+
| deptno | job       |
+--------+-----------+
|     20 | CLERK     |
|     30 | SALESMAN  |
|     20 | MANAGER   |
|     30 | MANAGER   |
|     10 | MANAGER   |
|     20 | ANALYST   |
|     10 | PRESIDENT |
|     30 | CLERK     |
|     10 | CLERK     |
+--------+-----------+	

案例:统计岗位的数量?

mysql> select count(distinct job) from emp;
+---------------------+
| count(distinct job) |
+---------------------+
|                   5 |
+---------------------+

统计每个部门岗位的数量?

mysql> select deptno,count(distinct job) from emp group by deptno;
+--------+---------------------+
| deptno | count(distinct job) |
+--------+---------------------+
|     10 |                   3 |
|     20 |                   3 |
|     30 |                   3 |
+--------+---------------------+

统计每个部门每个岗位员工的数量?

mysql> select deptno,job,count(distinct ename) from emp group by deptno,job;
+--------+-----------+-----------------------+
| deptno | job       | count(distinct ename) |
+--------+-----------+-----------------------+
|     10 | CLERK     |                     1 |
|     10 | MANAGER   |                     1 |
|     10 | PRESIDENT |                     1 |
|     20 | ANALYST   |                     2 |
|     20 | CLERK     |                     2 |
|     20 | MANAGER   |                     1 |
|     30 | CLERK     |                     1 |
|     30 | MANAGER   |                     1 |
|     30 | SALESMAN  |                     4 |
+--------+-----------+-----------------------+
2、连接查询
2.1什么是连接查询?

在实际开发过程中,大部分情况下不是从单表中查询数据,一般都是从多张表联合查询取出最终的结果。

在实际开发过程中,一般一个业务都会对应多张表,比如:学术和班级,起码两张表。

		stuno		stuname		classno		classname
		-------------------------------------------------------------
		1			zs			1			清华大学
		2			ls			1			清华大学
		...

学生和班级信息存储到一张表中,结果就像上面一样,数据会存在大量的重复,导致数据的冗余。

2.2连接查询的分类?

根据语法出现的年代来划分,包括:
SQL92(一些老的DBA可能还在使用这种语法。DBA:DataBase Administator,数据管理员)
SQL99(比较新的语法)

根据表的连接方式来划分,包括:
内连接:
等值连接
非等值连接
自连接
外连接:
左外连接(左连接)
右外连接(右链接)
全连接(很少使用)

2.3在表的连接查询方面有一种现象被称为:笛卡尔积现象。(笛卡尔乘积现象)

案例:找出每一个员工的部门名称,要求显示员工名和部门名。

	EMP表:
	mysql> select ename,deptno from emp;
	+--------+--------+
	| ename  | deptno |
	+--------+--------+
	| SMITH  |     20 |
	| ALLEN  |     30 |
	| WARD   |     30 |
	| JONES  |     20 |
	| MARTIN |     30 |
	| BLAKE  |     30 |
	| CLARK  |     10 |
	| SCOTT  |     20 |
	| KING   |     10 |
	| TURNER |     30 |
	| ADAMS  |     20 |
	| JAMES  |     30 |
	| FORD   |     20 |
	| MILLER |     10 |
	+--------+--------+
	DEPT表:
	mysql> select * from dept;
	+--------+------------+----------+
	| DEPTNO | DNAME      | LOC      |
	+--------+------------+----------+
	|     10 | ACCOUNTING | NEW YORK |
	|     20 | RESEARCH   | DALLAS   |
	|     30 | SALES      | CHICAGO  |
	|     40 | OPERATIONS | BOSTON   |
	+--------+------------+----------+
	
	mysql> select ename,dname from emp,dept;
	+--------+------------+
	| ename  | dname      |
	+--------+------------+
	| SMITH  | ACCOUNTING |
	| SMITH  | RESEARCH   |
	| SMITH  | SALES      |
	| SMITH  | OPERATIONS |
	| ALLEN  | ACCOUNTING |
	| ALLEN  | RESEARCH   |
	| ALLEN  | SALES      |
	| ALLEN  | OPERATIONS |
	......
	一共56条记录

笛卡尔现象:当两张表进行连接查询的时候,没有任何条件进行限制,最终的结果查询条数是两张表记录条数的乘积。

关于表的别名:

		select e.ename, d.dname from emp e,dept d;

表的别名有什么好处?
第一:执行效率高。(没有别名的话,找ename的时候会去emp dept两张表中都找,也可以避免两张表中有相同内容导致的错误)
第二:可读性好。

2.4怎么避免笛卡尔积现象?当然是加条件过滤。

思考:避免了笛卡尔积现象,会减少记录的匹配次数吗?
不会,次数还是56次,底层不会改变。只不过显示的是有效记录。

案例:找出每一个员工的部门名称,要求显示员工名和部门名称

		select
			e.ename, d.dname
		from
			emp e, dept d
		where
			e.deptno = d.deptno;  // SQL92,老语法,以后不用
		+--------+------------+
		| ename  | dname      |
		+--------+------------+
		| CLARK  | ACCOUNTING |
		| KING   | ACCOUNTING |
		| MILLER | ACCOUNTING |
		| SMITH  | RESEARCH   |
		| JONES  | RESEARCH   |
		| SCOTT  | RESEARCH   |
		| ADAMS  | RESEARCH   |
		| FORD   | RESEARCH   |
		| ALLEN  | SALES      |
		| WARD   | SALES      |
		| MARTIN | SALES      |
		| BLAKE  | SALES      |
		| TURNER | SALES      |
		| JAMES  | SALES      |
		+--------+------------+
2.5内连接之等值连接:最大特点是条件是等量关系。
案例:查询每个员工的部门名称,要求显示员工名和部门名。

		SQL92:(太老了,不用了)
			select 
				e.ename, d.dname 
			from 
				emp e,dept d 
			where 
				e.deptno = d.deptno;
				
		SQL99:(常用)
			select 
				e.ename, d.dname
			from
				emp e
			join
				dept d
			on
				e.deptno = d.deptno;
			
			// inner可以省略的,带着inner目的是可读性好一些。
			select 
				e.ename, d.dname
			from
				emp e
			inner join
				dept d
			on
				e.deptno = d.deptno;
				
			语法:
				...
					A
				join
					B
				on
					连接条件
				where
					...
					
SQL99语法结构更加清晰一些:表的连接条件和后来的where数据过滤条件分离了。
2.6内连接之非等值连接:最大的特点是:连接条件中的关系是非等量关系。
案例:要求找出每个员工的工资等级,要求显示员工名、工资、工资等级。

EMP表:
mysql> select ename,sal from emp;
+--------+---------+
| ename  | sal     |
+--------+---------+
| SMITH  |  800.00 |
| ALLEN  | 1600.00 |
| WARD   | 1250.00 |
| JONES  | 2975.00 |
| MARTIN | 1250.00 |
| BLAKE  | 2850.00 |
| CLARK  | 2450.00 |
| SCOTT  | 3000.00 |
| KING   | 5000.00 |
| TURNER | 1500.00 |
| ADAMS  | 1100.00 |
| JAMES  |  950.00 |
| FORD   | 3000.00 |
| MILLER | 1300.00 |
+--------+---------+
SALGRADE表:
mysql> select * from salgrade;
+-------+-------+-------+
| GRADE | LOSAL | HISAL |
+-------+-------+-------+
|     1 |   700 |  1200 |
|     2 |  1201 |  1400 |
|     3 |  1401 |  2000 |
|     4 |  2001 |  3000 |
|     5 |  3001 |  9999 |
+-------+-------+-------+

// inner可以省略
select 
	e.ename,e.sal,s.grade 
from 
	emp e 
inner join 
	salgrade s 
on 
	e.sal between s.losal and hisal;
+--------+---------+-------+
| ename  | sal     | grade |
+--------+---------+-------+
| SMITH  |  800.00 |     1 |
| ALLEN  | 1600.00 |     3 |
| WARD   | 1250.00 |     2 |
| JONES  | 2975.00 |     4 |
| MARTIN | 1250.00 |     2 |
| BLAKE  | 2850.00 |     4 |
| CLARK  | 2450.00 |     4 |
| SCOTT  | 3000.00 |     4 |
| KING   | 5000.00 |     5 |
| TURNER | 1500.00 |     3 |
| ADAMS  | 1100.00 |     1 |
| JAMES  |  950.00 |     1 |
| FORD   | 3000.00 |     4 |
| MILLER | 1300.00 |     2 |
+--------+---------+-------+
2.7自连接:最大特点是:一张表看做两张表。自己连自己
案例:找出每个员工的上级领导,要求显示员工名和对应的领导名。
mysql> select empno,ename,mgr from emp;
EMP a 员工表
+-------+--------+------+
| empno | ename  | mgr  |
+-------+--------+------+
|  7369 | SMITH  | 7902 |
|  7499 | ALLEN  | 7698 |
|  7521 | WARD   | 7698 |
|  7566 | JONES  | 7839 |
|  7654 | MARTIN | 7698 |
|  7698 | BLAKE  | 7839 |
|  7782 | CLARK  | 7839 |
|  7788 | SCOTT  | 7566 |
|  7839 | KING   | NULL |
|  7844 | TURNER | 7698 |
|  7876 | ADAMS  | 7788 |
|  7900 | JAMES  | 7698 |
|  7902 | FORD   | 7566 |
|  7934 | MILLER | 7782 |
+-------+--------+------+

EMP b 领导表(领导也是员工,也在emp表内)
+-------+--------+------+
| empno | ename  | mgr  |
+-------+--------+------+
|  7369 | SMITH  | 7902 |
|  7499 | ALLEN  | 7698 |
|  7521 | WARD   | 7698 |
|  7566 | JONES  | 7839 |
|  7654 | MARTIN | 7698 |
|  7698 | BLAKE  | 7839 |
|  7782 | CLARK  | 7839 |
|  7788 | SCOTT  | 7566 |
|  7839 | KING   | NULL |
|  7844 | TURNER | 7698 |
|  7876 | ADAMS  | 7788 |
|  7900 | JAMES  | 7698 |
|  7902 | FORD   | 7566 |
|  7934 | MILLER | 7782 |
+-------+--------+------+

员工的领导编号 = 领导的员工编号

select
	a.ename as '员工名', b.ename as '领导名'
from
	emp a
inner join
	emp b
on
	a.mgr = b.empno;
+--------+--------+
| 员工名 | 领导名 |
+--------+--------+
| SMITH  | FORD   |
| ALLEN  | BLAKE  |
| WARD   | BLAKE  |
| JONES  | KING   |
| MARTIN | BLAKE  |
| BLAKE  | KING   |
| CLARK  | KING   |
| SCOTT  | JONES  |
| TURNER | BLAKE  |
| ADAMS  | SCOTT  |
| JAMES  | BLAKE  |
| FORD   | JONES  |
| MILLER | CLARK  |
+--------+--------+
一共13条记录,King是老板,没有上级领导。
2.8外连接

什么是外连接?和内连接有什么区别?

	内连接:
		假设A和B表进行连接,使用内连接的话,凡是A表和B表能够匹配上的记录查询出来,这就是内连接。
		AB两张表没有祝福主副之分,两张表都是平等的。
	
	外连接:
		假设A和B表进行外连接的话,AB两张表中有一张表是主表,另一张是副表,主要是查询主表中的数据,
		捎带这查询副表。当副表中的数据没有和主表中的数据匹配上,副表自动模拟出NULL与之匹配。
		
	外连接的分类:
		左外连接(左连接):表示左边的这张表是主表。
		右外连接(右连接):表示右边的这张表是主表。
		
		左连接有右连接的写法,右连接也有对应左连接的写法。

案例:找出每个员工的上级领导,要求显示员工名和对应的领导名。(所有员工必须全部查询出来)

		内连接:
			select
				a.ename '员工', b.ename '领导'
			from
				emp a
			join
				emp b
			on
				a.mgr = b.empno;
		
		外连接:(左外连接/左连接)outer可以省略
			select
				a.ename '员工', b.ename '领导'
			from
				emp a
			left outer join
				emp b
			on
				a.mgr = b.empno;
				
		外连接:(右外连接/右连接)outer可以省略
			select
				a.ename '员工', b.ename '领导'
			from
				emp b
			right outer join
				emp a
			on
				a.mgr = b.empno;
			+--------+-------+
			| 员工   | 领导  |
			+--------+-------+
			| SMITH  | FORD  |
			| ALLEN  | BLAKE |
			| WARD   | BLAKE |
			| JONES  | KING  |
			| MARTIN | BLAKE |
			| BLAKE  | KING  |
			| CLARK  | KING  |
			| SCOTT  | JONES |
			| KING   | NULL  |
			| TURNER | BLAKE |
			| ADAMS  | SCOTT |
			| JAMES  | BLAKE |
			| FORD   | JONES |
			| MILLER | CLARK |
			+--------+-------+
			14 rows in set (0.00 sec)

外连接的最重要的特点:主表的数据无条件的全部查询出来。

	案例:找出哪个部门没有员工?
	EMP表:
	+-------+--------+--------+
	| empno | ename  | deptno |
	+-------+--------+--------+
	|  7369 | SMITH  |     20 |
	|  7499 | ALLEN  |     30 |
	|  7521 | WARD   |     30 |
	|  7566 | JONES  |     20 |
	|  7654 | MARTIN |     30 |
	|  7698 | BLAKE  |     30 |
	|  7782 | CLARK  |     10 |
	|  7788 | SCOTT  |     20 |
	|  7839 | KING   |     10 |
	|  7844 | TURNER |     30 |
	|  7876 | ADAMS  |     20 |
	|  7900 | JAMES  |     30 |
	|  7902 | FORD   |     20 |
	|  7934 | MILLER |     10 |
	+-------+--------+--------+
	DEPT表:
	+--------+------------+----------+
	| DEPTNO | DNAME      | LOC      |
	+--------+------------+----------+
	|     10 | ACCOUNTING | NEW YORK |
	|     20 | RESEARCH   | DALLAS   |
	|     30 | SALES      | CHICAGO  |
	|     40 | OPERATIONS | BOSTON   |
	+--------+------------+----------+
	
	select
		d.*
	from
		emp e
	right join
		dept d
	on
		e.deptno = d.deptno
	where
		e.ename is null;
	+--------+------------+--------+
	| DEPTNO | DNAME      | LOC    |
	+--------+------------+--------+
	|     40 | OPERATIONS | BOSTON |
	+--------+------------+--------+
2.9三张表怎么连接查询?
案例:找出每个员工的部门名称以及工资等级。
EMP表:
+-------+--------+--------+---------+
| empno | ename  | deptno | sal     |
+-------+--------+--------+---------+
|  7369 | SMITH  |     20 |  800.00 |
|  7499 | ALLEN  |     30 | 1600.00 |
|  7521 | WARD   |     30 | 1250.00 |
|  7566 | JONES  |     20 | 2975.00 |
|  7654 | MARTIN |     30 | 1250.00 |
|  7698 | BLAKE  |     30 | 2850.00 |
|  7782 | CLARK  |     10 | 2450.00 |
|  7788 | SCOTT  |     20 | 3000.00 |
|  7839 | KING   |     10 | 5000.00 |
|  7844 | TURNER |     30 | 1500.00 |
|  7876 | ADAMS  |     20 | 1100.00 |
|  7900 | JAMES  |     30 |  950.00 |
|  7902 | FORD   |     20 | 3000.00 |
|  7934 | MILLER |     10 | 1300.00 |
+-------+--------+--------+---------+

DEPT表:
+--------+------------+----------+
| DEPTNO | DNAME      | LOC      |
+--------+------------+----------+
|     10 | ACCOUNTING | NEW YORK |
|     20 | RESEARCH   | DALLAS   |
|     30 | SALES      | CHICAGO  |
|     40 | OPERATIONS | BOSTON   |
+--------+------------+----------+
SALGRADE表:
+-------+-------+-------+
| GRADE | LOSAL | HISAL |
+-------+-------+-------+
|     1 |   700 |  1200 |
|     2 |  1201 |  1400 |
|     3 |  1401 |  2000 |
|     4 |  2001 |  3000 |
|     5 |  3001 |  9999 |
+-------+-------+-------+

注意:
...
	A
join
	B
on
	...
join
	C
on
	...
表示:A表和B表先进行连接,连接之后A表继续和C表进行连接。

select
	e.ename,d.dname,s.grade
from
	emp e
join
	dept d 
on
	e.deptno = d.deptno
join
	salgrade s 
on
	e.sal between s.losal and s.hisal;
	
案例:找出每一个员工的部门名称、工资等级、上级领导
select
	e.ename '员工',d.dname '部门名称',s.grade '工资等级',e1.ename '领导'
from
	emp e
join
	dept d
on
	e.deptno = d.deptno
join
	salgrade s
on
	e.sal between s.losal and s.hisal
left join
	emp e1
on
	e.mgr = e1.empno;
+--------+------------+----------+-------+
| 员工   | 部门名称   | 工资等级 | 领导  |
+--------+------------+----------+-------+
| SMITH  | RESEARCH   |        1 | FORD  |
| ALLEN  | SALES      |        3 | BLAKE |
| WARD   | SALES      |        2 | BLAKE |
| JONES  | RESEARCH   |        4 | KING  |
| MARTIN | SALES      |        2 | BLAKE |
| BLAKE  | SALES      |        4 | KING  |
| CLARK  | ACCOUNTING |        4 | KING  |
| SCOTT  | RESEARCH   |        4 | JONES |
| KING   | ACCOUNTING |        5 | NULL  |
| TURNER | SALES      |        3 | BLAKE |
| ADAMS  | RESEARCH   |        1 | SCOTT |
| JAMES  | SALES      |        1 | BLAKE |
| FORD   | RESEARCH   |        4 | JONES |
| MILLER | ACCOUNTING |        2 | CLARK |
+--------+------------+----------+-------+
3、子查询
3.1什么是子查询?子查询都可以出现在哪里?

select语句中嵌套select语句,被嵌套的select语句是子查询。

子查询都可以出现在哪里?

		select
			..(select).
		from
			..(select).
		where
			..(select).
3.2 where子句中使用子查询
	案例:找出高于平均薪资的员工信息
		select ename,sal from emp where sal > avg(sal);  //错误写法,where后面不能直接跟分组函数
		mysql> select ename,sal from emp where sal >(select avg(sal) from emp);
		+-------+---------+
		| ename | sal     |
		+-------+---------+
		| JONES | 2975.00 |
		| BLAKE | 2850.00 |
		| CLARK | 2450.00 |
		| SCOTT | 3000.00 |
		| KING  | 5000.00 |
		| FORD  | 3000.00 |
		+-------+---------+
3.3 from后面嵌套子查询
	案例:找出每个部门平均薪水的工资等级
	select 
		t.* ,s.grade 
	from 
		(select deptno,avg(sal) as avgsal from emp group by deptno) t 
	join 
		salgrade s 
	on 
		t.avgsal between s.losal and hisal;
	+--------+-------------+-------+
	| deptno | avgsal      | grade |
	+--------+-------------+-------+
	|     30 | 1566.666667 |     3 |
	|     10 | 2916.666667 |     4 |
	|     20 | 2175.000000 |     4 |
	+--------+-------------+-------+
	
	案例:找出每个部门平均的薪水等级
	select 
		t.ed '部门编号', avg(t.sg) '平均薪资等级'
	from
		(select 
			e.ename,e.deptno as ed,s.grade as sg 
		from 
			emp e 
		join 
			salgrade s 
		on 
			e.sal between s.losal and s.hisal) t
	group by
		t.ed;
	+----------+--------------+
	| 部门编号 | 平均薪资等级 |
	+----------+--------------+
	|       10 |       3.6667 |
	|       20 |       2.8000 |
	|       30 |       2.5000 |
	+----------+--------------+
3.4 在select后面嵌套子查询
案例:找出每个员工所在的部门名称,要求显示员工名和部门名。
	以前用连接写过:
		select
			e.ename, d.name
		from 
			emp e
		join 
			dept d
		on
			e.deptno = d.deptno;
	
	如果用嵌套:
		select
			e.ename, (select d.dname from dept d where e.deptno = d.deptno) as dname
		from
			emp e;
4. union(可以将查询结果集相加)
案例:找出工作岗位是SALESMAN和MANAGER的员工?
	第一种:select ename,job from emp where job='SALESMAN' or job='MANAGER';
	第二种:select ename,job from emp where job in ('SALESMAN','MANAGER');
	第三种:使用union
	select ename,job from emp where job = 'MANAGER'
	union
	select ename,job from emp where job = 'SALESMAN';
	+--------+----------+
	| ename  | job      |
	+--------+----------+
	| JONES  | MANAGER  |
	| BLAKE  | MANAGER  |
	| CLARK  | MANAGER  |
	| ALLEN  | SALESMAN |
	| WARD   | SALESMAN |
	| MARTIN | SALESMAN |
	| TURNER | SALESMAN |
	+--------+----------+
两张不相干的表中数据拼接在一起显示? 
	select ename from emp
	union
	select dname from dept;  // ename和dname行数不一致,合并在一列了
	+------------+
	| ename      |
	+------------+
	| SMITH      |
	| ALLEN      |
	| WARD       |
	| JONES      |
	| MARTIN     |
	| BLAKE      |
	| CLARK      |
	| SCOTT      |
	| KING       |
	| TURNER     |
	| ADAMS      |
	| JAMES      |
	| FORD       |
	| MILLER     |
	| ACCOUNTING |
	| RESEARCH   |
	| SALES      |
	| OPERATIONS |
	+------------+

// 注意:当两个表列数不一致时会报错
mysql> select ename,sal from emp
	-> union
	-> select dname from dept;
ERROR 1222 (21000): The used SELECT statements have a different number of columns
5. limit(重点中的重点,以后分页查询全靠它)
5.1 limit是mysql特有的,其他数据库中没有,不通用。(Oracle中有一个相同的机制,叫做rownum)
5.2 limit取结果集中的部分数据,这是它的作用。
5.3 语法机制:
	limit startIndex, length
		startIndex表示起始位置,从0开始,0表示第一条数据
		length表示取几个
		
		startIndex可以省略不写,默认为0
	
	案例:取出工资前5名的员工
		select
			ename,sal
		from
			emp
		order by
			sal desc
		limit
			0,5;
		+-------+---------+
		| ename | sal     |
		+-------+---------+
		| KING  | 5000.00 |
		| SCOTT | 3000.00 |
		| FORD  | 3000.00 |
		| JONES | 2975.00 |
		| BLAKE | 2850.00 |
		+-------+---------+
5.4 limit是sql语句最后执行的一个环节:
	select
		...		5
	from
		...		1
	where
		...		2
	group by
		...		3
	having
		...		4
	order by
		...		6
	limit
		...;	7
5.5 通用的标准分页sql?
	每页显示3条记录:
	第1页:0,3
	第2页:3,3
	第3页:6,3
	...
	网站或者其他产品每页显示部分信息,这时就需要标准分页。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值