目录
一、什么地方可以使用别名,什么地方不可以?
结论:mysql中 group by、 order by、 having 后面可以使用别名,where后面不能使用别名
Oracle中 group by having where 中不能使用别名, order by 可以使用别名。
参照如下:
1)where/group by/having子句中只能直接使用栏位或者常量,而不能使用栏位的别名
2)而order by 则可以直接使用别名,如select col1 ccc from table order by ccc
MySQL :: MySQL 5.7 Reference Manual :: B.3.4.4 Problems with Column Aliases
分组语句中,select 和 from 之间,只能写分组字段和聚合函数
select gender,count(1) from user group by gender;
二、多表查询
1、笛卡尔集
笛卡尔:数学家(文艺工作者--百岁山)
select * from emp , dept;
发现有56条数据,组成了一个集合,称之为笛卡尔集。
结论:笛卡尔集是没有意义的,只有中间的一些数据有意义。
多表关联查询的本质就是-- 从笛卡尔集中过滤有意义的数据。
select * from emp , dept where emp.deptno = dept.deptno;
2、多表查询
分为:
内连接 inner join == join
外连接 左外连接 left outer join
右外连接 right outer join
outer 可以省略
select * from emp , dept where emp.deptno = dept.deptno;
对应的是标准sql中的内连接。
普通话的写法:
内连接的语法:
select 字段... from 表1 inner join 表2 on 条件
此时的inner 可以省略。
select * from emp inner join dept on emp.deptno = dept.deptno;
内连接:
左表和右边的数据,必须有关联,才能显示出来,否则左右两边的数据都不显示。
外连接:只要学会左外连接就万事大吉!
左外连接:
先要处理一个数据:
查询所有员工的基本信息,以及他对应的部门信息
此时chufaxingjin 也是该公司的员工,通过内连接无法查找出来。
此时就是典型的左连接:
左连接语法:
select 字段... from 表1 left outer join 表2 on 条件
sql语句编写:
select * from emp left outer join dept on emp.deptno = dept.deptno;
总结:
左外连接的意思是:以左表为主,左表的数据全部显示,能关联上右表的显示,关联不上的显示为null。
左连接和右连接 中的 outer 可以省略。
sql语句:
select * from emp left join dept on emp.deptno = dept.deptno;
右外连接:
左连接语法:
select 字段... from 表1 right outer join 表2 on 条件
sql语句编写:
select * from emp right outer join dept on emp.deptno = dept.deptno;
含义:以右表为主,右表的数据全部显示,能关联左表的显示,关联不上的,显示为null
所有的右连接都可以写成左连接.
比如:
select * from emp right outer join dept on emp.deptno = dept.deptno;
对应的效果一样的左连接的写法:
select * from dept left outer join emp on emp.deptno = dept.deptno;
效果是一样的:
如果表名特别⻓,每次写关联关系就特别的费劲,可以使⽤别名代替:
select * from dept left outer join emp on emp.deptno = dept.deptno;
添加完别名之后的写法:
select * from dept d left join emp e on e.deptno = d.deptno;
如果是想要两个表中的某些字段,该字段必须非常的明确:
mysql> select ename,sal,deptno,dname from emp e join dept d on e.deptno = d.deptno;
1052 - Column 'deptno' in field list is ambiguous (模棱两可)
修改一下:
select ename,sal,e.deptno,dname from emp e join dept d on e.deptno = d.deptno;
多表关联的时候,如果一个字段非常的明确,可以不在前面加表名,如果有多个表都有该字段,必须在字段前面指明是哪个表的字段,否则报错!!!
-- mysql 支持全连接吗? full join 不支持
select * from emp e left join dept d on e.deptno = d.deptno
union
select * from emp e right join dept d on e.deptno = d.deptno;
三、子查询(难点和重点)
⼦查询:当我们进⾏语句查询的时候,总会遇到我们需要的条件需要通过另⼀个查询语句查询出来后才能进⾏,就是说A 查询语句需要依赖B 查询语句的查询结果,B 查询就是⼦查询,A 查询语句就是主查询,⼀个SQL语句可以包含多个⼦查询。
1、⼯资⾼于JONES的员⼯
分析:JONES工资是多少?
select sal from emp where ename = 'JONES';
+---------+
| sal |
+---------+
| 2975.00 |
+---------+
工资高于2975的员工都有谁?
select * from emp where sal > 2975;
+-------+-------+-----------+------+------------+---------+------+--------+
| empno | ename | job | mgr | hiredate | sal | comm | deptno |
+-------+-------+-----------+------+------------+---------+------+--------+
| 7788 | SCOTT | ANALYST | 7566 | 1987-04-19 | 3000.00 | NULL | 20 |
| 7839 | KING | PRESIDENT | NULL | 1981-11-17 | 5000.00 | NULL | 10 |
| 7902 | FORD | ANALYST | 7566 | 1981-12-03 | 3000.00 | NULL | 20 |
+-------+-------+-----------+------+------------+---------+------+--------+
3 rows in set (0.08 sec)
一个语句写出来:
select * from emp where sal > (select sal from emp where ename = 'JONES');
2、查询与SCOTT同⼀个部⻔的员⼯
分析:SCOTT 所在的部门编号是多少?
select deptno from emp where ename='SCOTT';
+--------+
| deptno |
+--------+
| 20 |
+--------+
20号部门的员工都有谁?
select * from emp where deptno = 20 and ename !='SCOTT';
+-------+-------+---------+------+------------+---------+------+--------+
| empno | ename | job | mgr | hiredate | sal | comm | deptno |
+-------+-------+---------+------+------------+---------+------+--------+
| 7369 | SMITH | CLERK | 7902 | 1980-12-17 | 800.00 | NULL | 20 |
| 7566 | JONES | MANAGER | 7839 | 1981-04-02 | 2975.00 | NULL | 20 |
| 7876 | ADAMS | CLERK | 7788 | 1987-05-23 | 1100.00 | NULL | 20 |
| 7902 | FORD | ANALYST | 7566 | 1981-12-03 | 3000.00 | NULL | 20 |
+-------+-------+---------+------+------------+---------+------+--------+
最终的sql语句:
select * from emp where deptno = (select deptno from emp where ename='SCOTT') and ename !='SCOTT';
3、⼯资⾼于30号部⻔所有⼈的员⼯信息
分析:30号部门的最高工资是多少,大于这个最高工资就可以了。
select max(sal) from emp where deptno = 30;
+----------+
| max(sal) |
+----------+
| 2850.00 |
+----------+
select * from emp where sal > 2850;
+-------+-------+-----------+------+------------+---------+------+--------+
| empno | ename | job | mgr | hiredate | sal | comm | deptno |
+-------+-------+-----------+------+------------+---------+------+--------+
| 7566 | JONES | MANAGER | 7839 | 1981-04-02 | 2975.00 | NULL | 20 |
| 7788 | SCOTT | ANALYST | 7566 | 1987-04-19 | 3000.00 | NULL | 20 |
| 7839 | KING | PRESIDENT | NULL | 1981-11-17 | 5000.00 | NULL | 10 |
| 7902 | FORD | ANALYST | 7566 | 1981-12-03 | 3000.00 | NULL | 20 |
+-------+-------+-----------+------+------------+---------+------+--------+
嵌套起来:
select * from emp where sal > (select max(sal) from emp where deptno = 30);
子查询中返回的结果一般都是一个值,可以使用 = > < 等,否则会报错。
子查询出现的地方:
- 在where⼦句中: ⼦查询的结果可⽤作条件筛选时使⽤的值。
- 在from⼦句中: ⼦查询的结果可充当⼀张表或视图,需要使⽤表别名。
- 在having⼦句中: ⼦查询的结果可⽤作分组查询再次条件过滤时使⽤的值
- 在select⼦句中: ⼦查询的结果可充当⼀个字段。仅限⼦查询返回单⾏单列的情况。
1、查询⼯资⼤于10号部⻔的平均⼯资的⾮10号部⻔的员⼯信息
分析:
1)10号部⻔的平均⼯资
select avg(sal) from emp where deptno = 10;
2)查询员工信息
select * from emp where deptno != 10 and sal > (select avg(sal) from emp where deptno = 10);
+-------+-------+---------+------+------------+---------+------+--------+
| empno | ename | job | mgr | hiredate | sal | comm | deptno |
+-------+-------+---------+------+------------+---------+------+--------+
| 7566 | JONES | MANAGER | 7839 | 1981-04-02 | 2975.00 | NULL | 20 |
| 7788 | SCOTT | ANALYST | 7566 | 1987-04-19 | 3000.00 | NULL | 20 |
| 7902 | FORD | ANALYST | 7566 | 1981-12-03 | 3000.00 | NULL | 20 |
+-------+-------+---------+------+------------+---------+------+--------+
2、查询与7369同部⻔的同事信息
select deptno from emp where empno = 7369;
select * from emp where deptno = (select deptno from emp where empno = 7369)
and empno != 7369;
+-------+-------+---------+------+------------+---------+------+--------+
| empno | ename | job | mgr | hiredate | sal | comm | deptno |
+-------+-------+---------+------+------------+---------+------+--------+
| 7566 | JONES | MANAGER | 7839 | 1981-04-02 | 2975.00 | NULL | 20 |
| 7788 | SCOTT | ANALYST | 7566 | 1987-04-19 | 3000.00 | NULL | 20 |
| 7876 | ADAMS | CLERK | 7788 | 1987-05-23 | 1100.00 | NULL | 20 |
| 7902 | FORD | ANALYST | 7566 | 1981-12-03 | 3000.00 | NULL | 20 |
+-------+-------+---------+------+------------+---------+------+--------+
1、查询员⼯的姓名,⼯资,及其部⻔的平均⼯资
select ename,sal from emp ;
思考:
每一个部门的平均工资是多少?
select deptno,avg(sal) from emp group by deptno;
+--------+-------------+
| deptno | avg(sal) |
+--------+-------------+
| 10 | 2916.666667 |
| 20 | 2175.000000 |
| 30 | 1566.666667 |
| 100 | NULL |
+--------+-------------+
4 rows in set (0.09 sec)
查询员工信息:
select * from emp;
mysql> select * from emp;
+-------+--------+-----------+------+------------+---------+---------+--------+
| empno | ename | job | mgr | hiredate | sal | comm | deptno |
+-------+--------+-----------+------+------------+---------+---------+--------+
| 7369 | SMITH | CLERK | 7902 | 1980-12-17 | 800.00 | NULL | 20 |
| 7499 | ALLEN | SALESMAN | 7698 | 1981-02-20 | 1600.00 | 300.00 | 30 |
| 7521 | WARD | SALESMAN | 7698 | 1981-02-22 | 1250.00 | 500.00 | 30 |
| 7566 | JONES | MANAGER | 7839 | 1981-04-02 | 2975.00 | NULL | 20 |
| 7654 | MARTIN | SALESMAN | 7698 | 1981-09-28 | 1250.00 | 1400.00 | 30 |
| 7698 | BLAKE | MANAGER | 7839 | 1981-05-01 | 2850.00 | NULL | 30 |
| 7782 | CLARK | MANAGER | 7839 | 1981-06-09 | 2450.00 | NULL | 10 |
| 7788 | SCOTT | ANALYST | 7566 | 1987-04-19 | 3000.00 | NULL | 20 |
| 7839 | KING | PRESIDENT | NULL | 1981-11-17 | 5000.00 | NULL | 10 |
| 7844 | TURNER | SALESMAN | 7698 | 1981-09-08 | 1500.00 | 0.00 | 30 |
| 7876 | ADAMS | CLERK | 7788 | 1987-05-23 | 1100.00 | NULL | 20 |
| 7900 | JAMES | CLERK | 7698 | 1981-12-03 | 950.00 | NULL | 30 |
| 7902 | FORD | ANALYST | 7566 | 1981-12-03 | 3000.00 | NULL | 20 |
| 7934 | MILLER | CLERK | 7782 | 1982-01-23 | 1300.00 | NULL | 10 |
+-------+--------+-----------+------+------------+---------+---------+--------+
此时:查询出来的平均工资表可以当做一个虚拟的表,和emp表关联起来
mysql> select * from
( select deptno,avg(sal) avgMoney from emp group by deptno ) avgTable;
+--------+-------------+
| deptno | avgMoney |
+--------+-------------+
| 10 | 2916.666667 |
| 20 | 2175.000000 |
| 30 | 1566.666667 |
| 100 | NULL |
+--------+-------------+
现在 avgTable 表 和 emp 通过 deptno 相关联
select
ename,sal,avgMoney from
emp ,
(select deptno,avg(sal) avgMoney from emp group by deptno) avgTable
where emp.deptno=avgTable.deptno;
+--------+---------+-------------+
| ename | sal | avgMoney |
+--------+---------+-------------+
| SMITH | 800.00 | 2175.000000 |
| ALLEN | 1600.00 | 1566.666667 |
| WARD | 1250.00 | 1566.666667 |
| JONES | 2975.00 | 2175.000000 |
| MARTIN | 1250.00 | 1566.666667 |
| BLAKE | 2850.00 | 1566.666667 |
| CLARK | 2450.00 | 2916.666667 |
| SCOTT | 3000.00 | 2175.000000 |
| KING | 5000.00 | 2916.666667 |
| TURNER | 1500.00 | 1566.666667 |
| ADAMS | 1100.00 | 2175.000000 |
| JAMES | 950.00 | 1566.666667 |
| FORD | 3000.00 | 2175.000000 |
| MILLER | 1300.00 | 2916.666667 |
+--------+---------+-------------+
最终的答案!
虚拟机的表解释:--任何的查询结果都可以当做一个虚拟机的表来使用!
mysql> select ename,job,sal from emp where job is not null;
+--------+-----------+---------+
| ename | job | sal |
+--------+-----------+---------+
| SMITH | CLERK | 800.00 |
| ALLEN | SALESMAN | 1600.00 |
| WARD | SALESMAN | 1250.00 |
| JONES | MANAGER | 2975.00 |
| MARTIN | SALESMAN | 1250.00 |
| BLAKE | MANAGER | 2850.00 |
| CLARK | MANAGER | 2450.00 |
| SCOTT | ANALYST | 3000.00 |
| KING | PRESIDENT | 5000.00 |
| TURNER | SALESMAN | 1500.00 |
| ADAMS | CLERK | 1100.00 |
| JAMES | CLERK | 950.00 |
| FORD | ANALYST | 3000.00 |
| MILLER | CLERK | 1300.00 |
+--------+-----------+---------+
14 rows in set (0.09 sec)
mysql> select * from (select ename,job,sal from emp where job is not null) eemp;
+--------+-----------+---------+
| ename | job | sal |
+--------+-----------+---------+
| SMITH | CLERK | 800.00 |
| ALLEN | SALESMAN | 1600.00 |
| WARD | SALESMAN | 1250.00 |
| JONES | MANAGER | 2975.00 |
| MARTIN | SALESMAN | 1250.00 |
| BLAKE | MANAGER | 2850.00 |
| CLARK | MANAGER | 2450.00 |
| SCOTT | ANALYST | 3000.00 |
| KING | PRESIDENT | 5000.00 |
| TURNER | SALESMAN | 1500.00 |
| ADAMS | CLERK | 1100.00 |
| JAMES | CLERK | 950.00 |
| FORD | ANALYST | 3000.00 |
| MILLER | CLERK | 1300.00 |
+--------+-----------+---------+
14 rows in set (0.06 sec)
课堂上的sql:
-- 1、查询员⼯的姓名,⼯资,及其部⻔的平均⼯资
select ename,sal,deptno from emp;
select ename,sal,2000 from emp;
select avg(sal) from emp e2 where e2.deptno = 10;
select ename,sal,deptno,(select avg(sal) from emp e2 where e2.deptno = 20 ) as 该部门的平均工资 from emp e1;
select ename,sal,deptno dno,(select avg(sal) from emp e2 where deptno = dno ) as 该部门的平均工资 from emp e1;
-- 再来一种写法
select deptno,avg(sal) avgSal from emp group by deptno;
select deptno,avg(sal) avgSal from emp group by deptno having deptno=20;
select ename,sal,2000 from emp;
select ename,sal,(select avg(sal) avgSal from emp group by deptno having deptno = e1.deptno) as 该部门的平均工资 from emp e1;
-- 再来一种写法
select ename,sal,e2.avgSal from emp e1 , (select deptno,avg(sal) avgSal from emp group by deptno) e2
where e1.deptno = e2.deptno;
2、查询员⼯的姓名,⼯资,及其部⻔的平均⼯资
说一个情况: emp表和emp表也是可以自己关联自己的。
select * from emp e1, emp e2 where e1.empno = e2.empno;
select ename,sal, (select avg(sal) from emp e2 where e2.deptno = e1.deptno )
部门平均工资 from emp e1;
拆解:
select avg(sal) from emp e2 where e2.deptno = 10;
select avg(sal) from emp e2 where e2.deptno = 20;
最终的答案:
+--------+---------+--------------+
| ename | sal | 部门平均工资 |
+--------+---------+--------------+
| SMITH | 800.00 | 2175.000000 |
| ALLEN | 1600.00 | 1566.666667 |
| WARD | 1250.00 | 1566.666667 |
| JONES | 2975.00 | 2175.000000 |
| MARTIN | 1250.00 | 1566.666667 |
| BLAKE | 2850.00 | 1566.666667 |
| CLARK | 2450.00 | 2916.666667 |
| SCOTT | 3000.00 | 2175.000000 |
| KING | 5000.00 | 2916.666667 |
| TURNER | 1500.00 | 1566.666667 |
| ADAMS | 1100.00 | 2175.000000 |
| JAMES | 950.00 | 1566.666667 |
| FORD | 3000.00 | 2175.000000 |
| MILLER | 1300.00 | 2916.666667 |
+--------+---------+--------------+
优化一下:工资 保留小数点后2位
select ename,sal,
round(
( select avg(sal) from emp e2 where e2.deptno = e1.deptno),2) 部门平均工资
from emp e1;
+--------+---------+--------------+
| ename | sal | 部门平均工资 |
+--------+---------+--------------+
| SMITH | 800.00 | 2175.00 |
| ALLEN | 1600.00 | 1566.67 |
| WARD | 1250.00 | 1566.67 |
| JONES | 2975.00 | 2175.00 |
| MARTIN | 1250.00 | 1566.67 |
| BLAKE | 2850.00 | 1566.67 |
| CLARK | 2450.00 | 2916.67 |
| SCOTT | 3000.00 | 2175.00 |
| KING | 5000.00 | 2916.67 |
| TURNER | 1500.00 | 1566.67 |
| ADAMS | 1100.00 | 2175.00 |
| JAMES | 950.00 | 1566.67 |
| FORD | 3000.00 | 2175.00 |
| MILLER | 1300.00 | 2916.67 |
+--------+---------+--------------+
再来一遍,仔细品味:
mysql> select ename,sal, ( select avg(sal) from emp e2 where e2.deptno = 10 ) from emp;
+--------+---------+------------------------------------------------------+
| ename | sal | ( select avg(sal) from emp e2 where e2.deptno = 10 ) |
+--------+---------+------------------------------------------------------+
| SMITH | 800.00 | 2916.666667 |
| ALLEN | 1600.00 | 2916.666667 |
| WARD | 1250.00 | 2916.666667 |
| JONES | 2975.00 | 2916.666667 |
| MARTIN | 1250.00 | 2916.666667 |
| BLAKE | 2850.00 | 2916.666667 |
| CLARK | 2450.00 | 2916.666667 |
| SCOTT | 3000.00 | 2916.666667 |
| KING | 5000.00 | 2916.666667 |
| TURNER | 1500.00 | 2916.666667 |
| ADAMS | 1100.00 | 2916.666667 |
| JAMES | 950.00 | 2916.666667 |
| FORD | 3000.00 | 2916.666667 |
| MILLER | 1300.00 | 2916.666667 |
+--------+---------+------------------------------------------------------+
15 rows in set (0.10 sec)
mysql> select ename,sal, ( select avg(sal) from emp e2 where e2.deptno = emp.deptno ) from emp;
+--------+---------+--------------------------------------------------------------+
| ename | sal | ( select avg(sal) from emp e2 where e2.deptno = emp.deptno ) |
+--------+---------+--------------------------------------------------------------+
| SMITH | 800.00 | 2175.000000 |
| ALLEN | 1600.00 | 1566.666667 |
| WARD | 1250.00 | 1566.666667 |
| JONES | 2975.00 | 2175.000000 |
| MARTIN | 1250.00 | 1566.666667 |
| BLAKE | 2850.00 | 1566.666667 |
| CLARK | 2450.00 | 2916.666667 |
| SCOTT | 3000.00 | 2175.000000 |
| KING | 5000.00 | 2916.666667 |
| TURNER | 1500.00 | 1566.666667 |
| ADAMS | 1100.00 | 2175.000000 |
| JAMES | 950.00 | 1566.666667 |
| FORD | 3000.00 | 2175.000000 |
| MILLER | 1300.00 | 2916.666667 |
+--------+---------+--------------------------------------------------------------+
15 rows in set (0.11 sec)
再来一题:
查询每个员⼯的信息及其部⻔的平均⼯资,⼯资之和,部⻔⼈数
select *,
(select avg(sal) from emp e1 where e1.deptno = emp.deptno) 平均工资,
(select sum(sal) from emp e2 where e2.deptno = emp.deptno) 工资之和,
(select count(*) from emp e3 where e3.deptno = emp.deptno) 部门人数
from emp;
尝试-- 这种不行,报 Operand should contain 1 column(s)
select *,(
select avg(sal) 平均工资,sum(sal) 工资之和,count(*) 部门人数 from emp e1 where e1.deptno = emp.deptno) from emp;
改变思路:在玩一种很新的东西
mysql> select deptno,avg(sal) 平均工资,sum(sal) 工资之和,count(*) 部门人数 from emp e1
group by deptno ;
+--------+-------------+----------+----------+
| deptno | 平均工资 | 工资之和 | 部门人数 |
+--------+-------------+----------+----------+
| 10 | 2916.666667 | 8750.00 | 3 |
| 20 | 2175.000000 | 10875.00 | 5 |
| 30 | 1566.666667 | 9400.00 | 6 |
| 100 | NULL | NULL | 1 |
+--------+-------------+----------+----------+
硬套进去:失败了,原因是这个地方只允许出现一列数据
select * , (select * from (select deptno,avg(sal) 平均工资,sum(sal) 工资之和,count(*) 部门人数 from emp e1
group by deptno) pgb where pgb.deptno =emp.deptno ) from emp;
查询平均⼯资⼤于30号部⻔的平均⼯资的部⻔号,和平均⼯资
分析:30号部⻔的平均⼯资
select avg(sal) from emp where deptno = 30;
查询所有部门的平局工资:
select deptno,avg(sal) from emp group by deptno;
整合
select deptno,avg(sal) avgMoney from emp group by deptno
having avgMoney > (select avg(sal) from emp where deptno = 30);
+--------+-------------+
| deptno | avgMoney |
+--------+-------------+
| 10 | 2916.666667 |
| 20 | 2175.000000 |
+--------+-------------+
四、regexp 正则表达式
正则表达式:跨语言的一种写法
sql、java、js、python
书写正则表达式的规则是一模一样的,只是每一种语言调用的方式不同而已。
模糊查询: like regexp 两种
1、查询名字以l开头,以i结尾的数据
select * from stu where sname like 'l%i';
也可以使用正则表达式: 不太满足条件
select * from stu where sname regexp '^l|i$';
+--------+----------+-----+--------+
| sid | sname | age | gender |
+--------+----------+-----+--------+
| S_1001 | liuYi | 35 | male |
| S_1004 | liSi | 65 | female |
| S_1007 | sunQi | 25 | male |
| S_1010 | zhengShi | 5 | female |
+--------+----------+-----+--------+
-- . 表示任意字符除了\n 以外
* 表示出现 0 ~ 多次
select * from stu where sname regexp '^l.*i$';
+--------+-------+-----+--------+
| sid | sname | age | gender |
+--------+-------+-----+--------+
| S_1001 | liuYi | 35 | male |
| S_1004 | liSi | 65 | female |
+--------+-------+-----+--------+
练习:书写一个手机号码的正则表达式
^\d{11}$ -- 不太精准
^1[3456789]\d{9}$ -- 不太精准
-- 查询student 表中 ,手机号码正确的数据
select * from student where phone regexp '^1[3456789]\\d{9}$';
以上这个在mysql 8.0 中 \d 中的\ 需要转义。
select * from user where phone regexp '^1[3456789][0-9]{9}$';
练习:邮箱的正则表达式
9999@qq.com chufaxingjin@163.com laoli@ssr.net.cn
^.+@.+\..+$
练习正则的⽤法(此处没有表,只是⼀个sql⽽已,通过返回1还是0表示是否匹配)
mysql> select 'hello' regexp '^he';
+----------------------+
| 'hello' regexp '^he' |
+----------------------+
| 1 |
+----------------------+
1 row in set (0.06 sec)
mysql> select 'hello' regexp '^hh';
+----------------------+
| 'hello' regexp '^hh' |
+----------------------+
| 0 |
+----------------------+
1 row in set (0.08 sec)
mysql> select '9999@qq.com' regexp '^.+@.+\..+$';
+-----------------------------------------+
| '9999@qq.com' regexp '^.+@.+\..+$' |
+-----------------------------------------+
| 1 |
+-----------------------------------------+
1 row in set (0.06 sec)
-- 错误的
select 'chufaxingjin@163.' regexp '^.+@.+\..+$';
-- 改良的
-- \w 指的是 [0-9a-zA-z_]
select 'chufaxingjin@163.' regexp '^.+@.+[.]\\w+$';
-- qq 163 126 企业邮箱: chufaxingjin@qinzhuang.cn
select 'chufaxingjin@163.' regexp '^.+@.+[.].+$';
mysql> select '9999qq.com' regexp '^.+@.+[.].+$';
+----------------------------------------+
| '9999qq.com' regexp '^.+@.+\..+$' |
+----------------------------------------+
| 0 |
+----------------------------------------+
查找sname字段中包含'n'字符串的所有数据
select * from stu where sname like '%n%';
正则表达式:
select * from stu where sname regexp '^.*n.*$';
查找sname字段中以元⾳字符开头或以'ok'字符串结尾的所有数据
元音 a e i o u
select * from stu where sname regexp '^[aeiou]|ok$';
分享一个插件:
五、union 和 union all
造数据:
mysql> select * from a;
+----+------+
| id | name |
+----+------+
| 1 | a |
| 2 | b |
| 3 | c |
| 4 | d |
+----+------+
4 rows in set (0.07 sec)
mysql> select * from b;
+----+------+
| id | name |
+----+------+
| 3 | c |
| 4 | d |
| 5 | e |
| 6 | f |
+----+------+
4 rows in set (0.06 sec)
将两个表的结果集套在一起:
select * from a
union
select * from b;
+----+------+
| id | name |
+----+------+
| 1 | a |
| 2 | b |
| 3 | c |
| 4 | d |
| 5 | e |
| 6 | f |
+----+------+
union : 合并结果的时候,相同的数据可以去重。
select * from a
union all
select * from b;
+----+------+
| id | name |
+----+------+
| 1 | a |
| 2 | b |
| 3 | c |
| 4 | d |
| 3 | c |
| 4 | d |
| 5 | e |
| 6 | f |
+----+------+
伪SQL:
select tname,theight,tweight from teacher
union
select sname,sheight,sweight from student;
合并之后以第一个表的字段为主显示。
union all : 合并结果集,不去重
union 以及 union all 可以将左右两边的查询的结果进⾏合并
union 如果左右两边的数据是重复的,可以虑重
union all 没有虑重的功能。
并且左右两边的查询结果的列数必须相同,并且列的数据类型也必须相同,列的名称可以不同。
如果两张表中的字段列数不相同,只要查询的字段相同即可。
mysql> select empno,ename from emp union all select sid,sname from stu;
+--------+----------+
| empno | ename |
+--------+----------+
| 7369 | SMITH |
| 7499 | ALLEN |
| 7521 | WARD |
| 7566 | JONES |
| 7654 | MARTIN |
| 7698 | BLAKE |
| 7782 | CLARK |
| 7788 | SCOTT |
| 7839 | KING |
| 7844 | TURNER |
| 7876 | ADAMS |
| 7900 | JAMES |
| 7902 | FORD |
| 7934 | MILLER |
| S_1001 | liuYi |
| S_1002 | chenEr |
| S_1003 | zhangSan |
| S_1004 | liSi |
| S_1005 | wangWu |
| S_1006 | zhaoLiu |
| S_1007 | sunQi |
| S_1008 | zhouBa |
| S_1009 | wuJiu |
| S_1010 | zhengShi |
| S_1011 | xxx |
+--------+----------+
六、小练习
1、查询员工属于哪个部门,并且把部门信息展示一下
2、查询员工姓名和所属部门名称
3、工资高于JONES的员工
4、查询与SCOTT同一个部门的员工
5、工资高于30号部门所有人的员工信息
6、查询所有员工信息以及工资总和
7、查询工资最高TOP 5
8、查询员工表中第6到第12条数据
9、查询所有不是部门经理的员工
10、查询所有员工人数不少于3人的部门信息
11、查询员工编号,姓名,部门编号,工资,本部门工资总和
12、查询每个员工的姓名和上级领导的姓名
# 1、查询员工属于哪个部门,并且把部门信息展示一下
select emp.*,dept.dname from emp,dept where emp.deptno=dept.deptno;
# 2、查询员工姓名和所属部门名称
select emp.ename,dept.dname from emp,dept where emp.deptno=dept.deptno;
# 3、工资高于JONES的员工
# 4、查询与SCOTT同一个部门的员工
# 5、工资高于30号部门所有人的员工信息
# 6、查询所有员工信息以及工资总和
select *,(select sum(sal) from emp) 工资总和 from emp;
# 7、查询工资最高TOP 5
select * from emp order by sal desc limit 5;
# 8、查询员工表中第6到第12条数据
select * from emp limit 5,7;
# 9、查询所有不是部门经理的员工
select * from emp where job !='MANAGER';
# 10、查询所有员工人数不少于3人的部门信息
select deptno,count(1) from emp group by deptno having count(1) >=3;
-- 第一种写法
select * from dept where deptno in (select deptno from emp group by deptno having count(1) >=3);
select * from dept d1 where exists( select deptno from emp group by deptno having count(1) >=3 and deptno = d1.deptno);
-- 偏不使用别名
select d1.*,e1.`count(1)` from dept d1 ,(select deptno,count(1) from emp group by deptno having count(1) >=3) e1
where d1.deptno = e1.deptno;
-- 使用别名
select d1.*,e1.totalNum from dept d1 ,(select deptno,count(1) totalNum from emp group by deptno having totalNum >=3) e1
where d1.deptno = e1.deptno;
# 11、查询员工编号,姓名,部门编号,工资,本部门工资总和
desc emp;
select empno,ename,deptno,sal,(select sum(sal) from emp e1 where e1.deptno=e2.deptno) '部门工资总和' from emp e2;
# 12、查询每个员工的姓名和上级领导的姓名
select e1.ename,(select e2.ename from emp e2 where e2.empno = e1.mgr) 领导姓名 from emp e1;
select * from emp where ename='JONES';
select * from emp where empno = 7839;