一、简单的查询语句 (DQL)
语法格式:select 字段名1,字段名2,字段名3,...... from 表名
";" 结尾
不区分大小写
mysql> select ENAME from emp; mysql> select Ename From EmP;
+--------+ +--------+
| ENAME | | Ename |
+--------+ +--------+
| SMITH | | SMITH |
| ALLEN | | ALLEN |
| WARD | | WARD |
| JONES | | JONES |
| MARTIN | | MARTIN |
| BLAKE | | BLAKE |
| CLARK | | CLARK |
| SCOTT | | SCOTT |
| KING | | KING |
| TURNER | | TURNER |
| ADAMS | | ADAMS |
| JAMES | | JAMES |
| FORD | | FORD |
| MILLER | | MILLER |
+--------+ +--------+
字段可以参与数学运算:
mysql> select sal * 12 from emp;
+----------+
| sal * 12 |
+----------+
| 9600.00 |
| 19200.00 |
| 15000.00 |
| 35700.00 |
| 15000.00 |
| 34200.00 |
| 29400.00 |
| 36000.00 |
| 60000.00 |
| 18000.00 |
| 13200.00 |
| 11400.00 |
| 36000.00 |
| 15600.00 |
+----------+
怎么对列重命名?: 加一个 as 的语句,如果要使用中文字符, 用单引号括起来 ,不要用双引号
as 关键字可以省略,用空格分割即可。
mysql> select sal *12 as yearsal from emp;
+----------+
| yearsal |
+----------+
| 9600.00 |
| 19200.00 |
| 15000.00 |
| 35700.00 |
| 15000.00 |
| 34200.00 |
| 29400.00 |
| 36000.00 |
| 60000.00 |
| 18000.00 |
| 13200.00 |
| 11400.00 |
| 36000.00 |
| 15600.00 |
+----------+
可以通过 select * from table_name 的方法查询表中的所有字段,但效率很低,不建议使用。
想要你查询所有字段,可以通过 select 字段名,字段名 from table_name 的方法,列出所有的字段名。
二、条件查询
语法格式:
select
字段名
from
表名
where
条件;执行顺序:from ---- where ---- select
例:查找月薪为5000的员工名称
mysql> select ename from emp where sal=5000;
+-------+
| ename |
+-------+
| KING |
+-------+
找出哪些人津贴不为null: 用 is null 运算符
mysql> select ename from emp where COMM is null;
+--------+
| ename |
+--------+
| SMITH |
| JONES |
| BLAKE |
| CLARK |
| SCOTT |
| KING |
| ADAMS |
| JAMES |
| FORD |
| MILLER |
+--------+
1. 查询语句中关于 between...and 的用法:
可以用于查找某两个数范围内的值,也可以用来查找字符串:
mysql> select ename from emp where sal between 1000 and 3000;
+--------+
| ename |
+--------+
| ALLEN |
| WARD |
| JONES |
| MARTIN |
| BLAKE |
| CLARK |
| SCOTT |
| TURNER |
| ADAMS |
| FORD |
| MILLER |
+--------+
mysql> select empno,ename from emp where ename between 'a' and 'c';
+-------+-------+
| empno | ename |
+-------+-------+
| 7499 | ALLEN |
| 7698 | BLAKE |
| 7876 | ADAMS |
+-------+-------+
但在限制因素为数字时,between and表示的为全包区间,而如果是字符串,则为左闭右开区间。
2. 查询语句中关于 and 和 or / in 的优先级问题
例:找到工作岗位是MANAGER的员工和SALESMAN的员工:
mysql> select ename,job from emp where job = 'salesman' or job= 'manager';
+--------+----------+
| ename | job |
+--------+----------+
| ALLEN | SALESMAN |
| WARD | SALESMAN |
| JONES | MANAGER |
| MARTIN | SALESMAN |
| BLAKE | MANAGER |
| CLARK | MANAGER |
| TURNER | SALESMAN |
+--------+----------+
例:and和or联合起来用,找出薪资大于3000且部门编号是20或30部门的员工,要注意and的优先级比or高
mysql> select ename,deptno from emp where sal>1000 and (deptno=10 or deptno=30);
+--------+--------+
| ename | deptno |
+--------+--------+
| ALLEN | 30 |
| WARD | 30 |
| MARTIN | 30 |
| BLAKE | 30 |
| CLARK | 10 |
| KING | 10 |
| TURNER | 30 |
| MILLER | 10 |
+--------+--------+
例:找出工作岗位是MANAGER和SALESMAN的员工,可以用 ‘in’ 代替 ‘or’ 来使用,要注意 ‘in’ 指的是具体的值,不是范围:
mysql> select ename,job from emp where job in ('salesman','manager');
+--------+----------+
| ename | job |
+--------+----------+
| ALLEN | SALESMAN |
| WARD | SALESMAN |
| JONES | MANAGER |
| MARTIN | SALESMAN |
| BLAKE | MANAGER |
| CLARK | MANAGER |
| TURNER | SALESMAN |
+--------+----------+
3. 查询语句中关于 模糊查询 的实现:用 like 方法
在模糊查询中,需要掌握两个符号:‘ % ’代表任意多个字符,‘ _ ’代表任意一个字符。
例:找出名字中带有‘O’的员工
mysql> select ename from emp where ename like '%O%';
+-------+
| ename |
+-------+
| JONES |
| SCOTT |
| FORD |
+-------+
这里,必须要用关键词 like ,表示模糊查询, %O% 表示前面有任意字符,后面有任意字符,中间必须含有O。
例:找出名字中第二个字母是A的员工
mysql> select ename from emp where ename like '_A%';
+--------+
| ename |
+--------+
| WARD |
| MARTIN |
| JAMES |
+--------+
_A% , _ 表示任意的一个字符,即第一位任意,第二位为A,后续为任意字符。
例:如果查找的条件中含有‘ _ ’或‘ % ’:需要进行转义
mysql> select ename from emp where ename like '%\_%';
Empty set (0.00 sec)
4. 查询语句中数据排序的实现:用 order by 方法
默认是升序排列,如需指定, asc 表示升序, desc 表示降序。
例:按照员工工资排序
mysql> select ename,sal from emp order by sal; //升序
+--------+---------+
| ename | sal |
+--------+---------+
| SMITH | 800.00 |
| JAMES | 950.00 |
| ADAMS | 1100.00 |
| WARD | 1250.00 |
| MARTIN | 1250.00 |
| MILLER | 1300.00 |
| TURNER | 1500.00 |
| ALLEN | 1600.00 |
| CLARK | 2450.00 |
| BLAKE | 2850.00 |
| JONES | 2975.00 |
| FORD | 3000.00 |
| SCOTT | 3000.00 |
| KING | 5000.00 |
+--------+---------+
mysql> select ename,sal from emp order by sal asc; //升序
+--------+---------+
| ename | sal |
+--------+---------+
| SMITH | 800.00 |
| JAMES | 950.00 |
| ADAMS | 1100.00 |
| WARD | 1250.00 |
| MARTIN | 1250.00 |
| MILLER | 1300.00 |
| TURNER | 1500.00 |
| ALLEN | 1600.00 |
| CLARK | 2450.00 |
| BLAKE | 2850.00 |
| JONES | 2975.00 |
| FORD | 3000.00 |
| SCOTT | 3000.00 |
| KING | 5000.00 |
+--------+---------+
mysql> select ename,sal from emp order by sal desc; //降序
+--------+---------+
| ename | sal |
+--------+---------+
| KING | 5000.00 |
| SCOTT | 3000.00 |
| FORD | 3000.00 |
| JONES | 2975.00 |
| BLAKE | 2850.00 |
| CLARK | 2450.00 |
| ALLEN | 1600.00 |
| TURNER | 1500.00 |
| MILLER | 1300.00 |
| MARTIN | 1250.00 |
| WARD | 1250.00 |
| ADAMS | 1100.00 |
| JAMES | 950.00 |
| SMITH | 800.00 |
+--------+---------+
例:按照工资排序,工资相同时按名字降序排
排序的标准用 ‘ , ’ 进行分割,排在前面的标准优先度高
mysql> select ename,sal from emp order by sal asc, ename desc;
+--------+---------+
| ename | sal |
+--------+---------+
| SMITH | 800.00 |
| JAMES | 950.00 |
| ADAMS | 1100.00 |
| WARD | 1250.00 |
| MARTIN | 1250.00 |
| MILLER | 1300.00 |
| TURNER | 1500.00 |
| ALLEN | 1600.00 |
| CLARK | 2450.00 |
| BLAKE | 2850.00 |
| JONES | 2975.00 |
| SCOTT | 3000.00 |
| FORD | 3000.00 |
| KING | 5000.00 |
+--------+---------+
例:找出工作岗位是SALESMAN的员工并按照工资进行升序排列
执行顺序
select
* 3
from
tablename 1
where
条件 2
order by
........; 4
mysql> select ename,sal,job from emp where job = 'salesman' order by sal asc;
+--------+---------+----------+
| ename | sal | job |
+--------+---------+----------+
| WARD | 1250.00 | SALESMAN |
| MARTIN | 1250.00 | SALESMAN |
| TURNER | 1500.00 | SALESMAN |
| ALLEN | 1600.00 | SALESMAN |
+--------+---------+----------+
5、分组函数
count 计数
sum 求和
max 最大值
min 最小值
avg 平均值
一共5个,需要对一组数据进行操作,又叫多行处理函数,输入多行输出一行
分组函数会自动忽略null值
找出工资总和:
select sum(sal) from emp;
找出最高工资:
select max(sal) from emp;
找出总人数:
select count(ename) from emp;
select count(*) from emp;
找出平均工资:
select avg(sal) from emp;
例:找出工资高于平均工资的员工
mysql> select ename,sal from emp where sal>avg(sal);
ERROR 1111 (HY000): Invalid use of group function
直接在where语句中使用分组函数会报错,分组函数不可以直接用于where子句
count (*)和count具体的某个字段有什么区别?
count(*)统计的是总记录条数,和某个字段无关
count(某个字段)统计的是某个字段中不为null的个数
group by 和 having 的用法
group by:按照某个字段或某些字段进行分组
having:对分组后的数据再次进行分类
分组函数一般都会和group by联合起来使用,并且都是在group by语句执行结束之后才会执行。
当SQL语句没有group by时,整张表的数据自成一组。
例:找出每个工作岗位的最高薪资
mysql> select ename,job,max(sal) from emp group by job;
+-------+-----------+----------+
| ename | job | max(sal) |
+-------+-----------+----------+
| SCOTT | ANALYST | 3000.00 |
| SMITH | CLERK | 1300.00 |
| JONES | MANAGER | 2975.00 |
| KING | PRESIDENT | 5000.00 |
| ALLEN | SALESMAN | 1600.00 |
+-------+-----------+----------+
***对where后面不能使用分组函数的理解:
主要与语句的执行顺序有关。
执行顺序
select
...... 5
from
...... 1
where
先执行where语句
group by
3 再执行group by语句
having
....... 4
order by
....... 6
例:找出薪水高于平均薪资的员工
如果在where后面使用了分组函数:
select ename,sal from emp where sal>avg(sal);
那么在执行where语句之前,avg(sal)就需要先被执行,但avg()函数执行的条件是先分组,只有先分组了才能使用分组语句,就算没有显式的写出分组语句,如:
select ename from emp;
也暗含了一个缺省的group by,会把整个表分为一组。
因此在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 |
+-------+---------+
***当 一条语句有group by,select后面只能跟参加分组的字段或分组函数,别的不能写,输出的内容没有意义
mysql> select ename,job,max(sal) from emp group by job;
+-------+-----------+----------+
| ename | job | max(sal) |
+-------+-----------+----------+
| SCOTT | ANALYST | 3000.00 |
| SMITH | CLERK | 1300.00 |
| JONES | MANAGER | 2975.00 |
| KING | PRESIDENT | 5000.00 |
| ALLEN | SALESMAN | 1600.00 |
+-------+-----------+----------+
在案例中,按照job进行分组聚合,分组字段是job。
此上,在mysql中,查询结果是有的,但没有意义,ename不是分组字段,查询到的几个数据都是随机的,没有对应关系。
若在Oracle中,就会抱语法错误。
select 后面只能跟分组函数或分组字段。
****多个字段进行联合分组
直接在group by后面写需要进行联合的字段:
例:找到各个部门不同工作岗位的最高薪资
select deptno,job,max(sal) from emp group by deptno,job; //按照job和deptno进行联合分组
mysql> select deptno,job,max(sal) from emp group by deptno,job;
+--------+-----------+----------+
| deptno | job | max(sal) |
+--------+-----------+----------+
| 10 | CLERK | 1300.00 |
| 10 | MANAGER | 2450.00 |
| 10 | PRESIDENT | 5000.00 |
| 20 | ANALYST | 3000.00 |
| 20 | CLERK | 1100.00 |
| 20 | MANAGER | 2975.00 |
| 30 | CLERK | 950.00 |
| 30 | MANAGER | 2850.00 |
| 30 | SALESMAN | 1600.00 |
+--------+-----------+----------+
例:找到每个部门的最高薪资,要求显示薪资大于2500的数据
mysql> select max(sal) from emp group by deptno having max(sal)>2900; //效率低
+----------+
| max(sal) |
+----------+
| 5000.00 |
| 3000.00 |
+----------+
2 rows in set (0.00 sec)
mysql> select max(sal) from emp where sal>2900 group by deptno; //效果更好
+----------+
| max(sal) |
+----------+
| 5000.00 |
| 3000.00 |
+----------+
2 rows in set (0.00 sec)
建议能用where的就用where。
但也存在不能用where只能用having的情况:
例:找出平均薪资大于2000的部门
mysql> select deptno,avg(sal) from emp group by deptno having avg(sal)>2000;
+--------+-------------+
| deptno | avg(sal) |
+--------+-------------+
| 10 | 2916.666667 |
| 20 | 2175.000000 |
+--------+-------------+
2 rows in set (0.00 sec)
此时就无法使用where的方法进行选择,只能用having,因为对于平均薪资来说,不能在分组之前就进行筛选,而是必须放在分组之后。
****关于查询结果集的去重
用distinct关键字,distinct只能出现在所有字段的最前面,是对后面所有字段联合起来的去重。
mysql> select job from emp;
+-----------+
| job |
+-----------+
| CLERK |
| SALESMAN |
| SALESMAN |
| MANAGER |
| SALESMAN |
| MANAGER |
| MANAGER |
| ANALYST |
| PRESIDENT |
| SALESMAN |
| CLERK |
| CLERK |
| ANALYST |
| CLERK |
+-----------+
mysql> select distinct job from emp;
+-----------+
| job |
+-----------+
| CLERK |
| SALESMAN |
| MANAGER |
| ANALYST |
| PRESIDENT |
+-----------+