MySql学习笔记03——DQL(数据查询)基本命令
DQL
导入数据
首先使用use database
进入数据库中,然后使用命令
source D:\mysql_learning\mysql_learning\document\bjpowernode.sql
注意文件名不能有双引号,命令结尾没有分号。
SQL脚本
.sql
文件是SQL脚本文件,它里面的内容都是SQL语句,当调用这个文件的时候就会执行文件里面的所有语句。
批量的执行SQL语句,可以使用sql脚本文件。
在mysql当中怎么执行sql脚本呢?
sourse 脚本路径
你在实际的工作中,第一天到了公司,项目经理会给你一个xxx.sql文件,你执行这个脚本文件,你电脑上的数据库数据就有了!
查看表结构
mysql> show tables;
+------------------------+
| Tables_in_bjpowernnode |
+------------------------+
| dept |
| emp |
| salgrade |
+------------------------+
查看表中的数据
select * from 表名;
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 |
+-------+--------+-----------+------+------------+---------+---------+--------+
不看表中的数据,只看表中的结构
desc 表名;
mysql> desc emp;
+----------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+-------+
| EMPNO | int | NO | PRI | NULL | | # varchar就是string
| ENAME | varchar(10) | YES | | NULL | |
| JOB | varchar(9) | YES | | NULL | |
| MGR | int | YES | | NULL | |
| HIREDATE | date | YES | | NULL | |
| SAL | double(7,2) | YES | | NULL | |
| COMM | double(7,2) | YES | | NULL | |
| DEPTNO | int | YES | | NULL | |
+----------+-------------+------+-----+---------+-------+
简单查询
简单查询都是和
select
相关的操作,只要是和select
相关的操作都不会对原表中的数据进行修改,只会进行查询操作。
查询一个字段
select 字段名 from 表名;
查询多个字段
select 字段名1,字段名2... from 表名;# 用逗号将多个字段名分隔开
查询所有字段
# 一种方式是
select a,b,c,d.... from 表名;
#另外一种方式是
select * from 表名;
但是第二种方式一般效率较低,不是很推荐。
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 |
+-------+--------+-----------+------+------------+---------+---------+--------+
14 rows in set (0.00 sec)mysql> select Job,Sal from emp;
+-----------+---------+
| Job | Sal |
+-----------+---------+
| CLERK | 800.00 |
| SALESMAN | 1600.00 |
| SALESMAN | 1250.00 |
| MANAGER | 2975.00 |
| SALESMAN | 1250.00 |
| MANAGER | 2850.00 |
| MANAGER | 2450.00 |
| ANALYST | 3000.00 |
| PRESIDENT | 5000.00 |
| SALESMAN | 1500.00 |
| CLERK | 1100.00 |
| CLERK | 950.00 |
| ANALYST | 3000.00 |
| CLERK | 1300.00 |
+-----------+---------+
14 rows in set (0.00 sec)
给查询的列取别名,按照别名来进行显示
select 字段名 as 别名 from 表名;
mysql> select Job,Sal as salary from emp;
+-----------+---------+
| Job | salary |
+-----------+---------+
| CLERK | 800.00 |
| SALESMAN | 1600.00 |
| SALESMAN | 1250.00 |
| MANAGER | 2975.00 |
| SALESMAN | 1250.00 |
| MANAGER | 2850.00 |
| MANAGER | 2450.00 |
| ANALYST | 3000.00 |
| PRESIDENT | 5000.00 |
| SALESMAN | 1500.00 |
| CLERK | 1100.00 |
| CLERK | 950.00 |
| ANALYST | 3000.00 |
| CLERK | 1300.00 |
+-----------+---------+
14 rows in set (0.00 sec)
注意,这里的取别名只会对显示的列显示别名的效果,不会对原本的表中的列名进行修改。
同时,as
关键字是可以被省略的,用空格代替,如果别名中的含有空格,需要用单引号将别名括起来,当然,使用双引号也行,但是oracle
中不支持双引号进行这样的操作,因此还是统一使用单引号。
列参进行数学运算
字段是支持直接进行数学运算的,例如:
mysql> select ename, sal * 12 as "year's salary" from emp;
+--------+---------------+
| ename | year's salary |
+--------+---------------+
| SMITH | 9600.00 |
| ALLEN | 19200.00 |
| WARD | 15000.00 |
| JONES | 35700.00 |
| MARTIN | 15000.00 |
| BLAKE | 34200.00 |
| CLARK | 29400.00 |
| SCOTT | 36000.00 |
| KING | 60000.00 |
| TURNER | 18000.00 |
| ADAMS | 13200.00 |
| JAMES | 11400.00 |
| FORD | 36000.00 |
| MILLER | 15600.00 |
+--------+---------------+
14 rows in set (0.01 sec)
这样久能实现查看到年薪是多少了,同时还取了个别名。
条件查询
查询出符合条件的内容
select 字段名1,字段名2...from 表名 where 条件;
主要使用的一些条件
等于=
mysql> select ename,job,sal from emp where sal=1250;# 找到工资为1250的人
+--------+----------+---------+
| ename | job | sal |
+--------+----------+---------+
| WARD | SALESMAN | 1250.00 |
| MARTIN | SALESMAN | 1250.00 |
+--------+----------+---------+
2 rows in set (0.00 sec)# 当然也支持数学运算
mysql> select ename,job,sal from emp where sal*8=10000;
+--------+----------+---------+
| ename | job | sal |
+--------+----------+---------+
| WARD | SALESMAN | 1250.00 |
| MARTIN | SALESMAN | 1250.00 |
+--------+----------+---------+
2 rows in set (0.00 sec)#也是支持查找字符串的
mysql> select ename,job,sal from emp where ename='SMITH';
+-------+-------+--------+
| ename | job | sal |
+-------+-------+--------+
| SMITH | CLERK | 800.00 |
+-------+-------+--------+
1 row in set (0.00 sec)
不等于!=或者<>
mysql> select ename,job,sal from emp where sal!=1250;
+--------+-----------+---------+
| ename | job | sal |
+--------+-----------+---------+
| SMITH | CLERK | 800.00 |
| ALLEN | SALESMAN | 1600.00 |
| JONES | MANAGER | 2975.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 |
+--------+-----------+---------+
12 rows in set (0.00 sec)
小于<
大于>
大于等于>=
小于等于<=
上面的都是类似的
- 区间
between...and...
严格的要求左小右大,同时between…and…是闭区间,包括两端的值() and ()
mysql> select ename,job,sal from emp where sal>=950 and sal<3000;
+--------+----------+---------+
| ename | job | sal |
+--------+----------+---------+
| ALLEN | SALESMAN | 1600.00 |
| WARD | SALESMAN | 1250.00 |
| JONES | MANAGER | 2975.00 |
| MARTIN | SALESMAN | 1250.00 |
| BLAKE | MANAGER | 2850.00 |
| CLARK | MANAGER | 2450.00 |
| TURNER | SALESMAN | 1500.00 |
| ADAMS | CLERK | 1100.00 |
| JAMES | CLERK | 950.00 |
| MILLER | CLERK | 1300.00 |
+--------+----------+---------+
10 rows in set (0.01 sec)
is null /is not null
null在mysql中表示没有,如果用=或者!=表示查找为值为空的,那样是找不到null元素的
# is not null
mysql> select ename,job,comm from emp where COMM is not null;
+--------+----------+---------+
| ename | job | comm |
+--------+----------+---------+
| ALLEN | SALESMAN | 300.00 |
| WARD | SALESMAN | 500.00 |
| MARTIN | SALESMAN | 1400.00 |
| TURNER | SALESMAN | 0.00 |
+--------+----------+---------+
4 rows in set (0.00 sec)# is null
mysql> select ename,job,comm from emp where COMM is null;
+--------+-----------+------+
| ename | job | comm |
+--------+-----------+------+
| SMITH | CLERK | NULL |
| JONES | MANAGER | NULL |
| BLAKE | MANAGER | NULL |
| CLARK | MANAGER | NULL |
| SCOTT | ANALYST | NULL |
| KING | PRESIDENT | NULL |
| ADAMS | CLERK | NULL |
| JAMES | CLERK | NULL |
| FORD | ANALYST | NULL |
| MILLER | CLERK | NULL |
+--------+-----------+------+
10 rows in set (0.00 sec)
and/or/not
and表示并且,or表示或者,and和or同时出现的时候会有优先级问题,and的优先级更高,如果想优先使用or,就用小括号括起来,not 就是表示否,一般和is 和 in 一起用 ,is not null / not in
mysql> select ename,job,sal from emp where job='MANAGER' or job='SALESMAN';
+--------+----------+---------+
| ename | job | sal |
+--------+----------+---------+
| ALLEN | SALESMAN | 1600.00 |
| WARD | SALESMAN | 1250.00 |
| JONES | MANAGER | 2975.00 |
| MARTIN | SALESMAN | 1250.00 |
| BLAKE | MANAGER | 2850.00 |
| CLARK | MANAGER | 2450.00 |
| TURNER | SALESMAN | 1500.00 |
+--------+----------+---------+
7 rows in set (0.00 sec)
in
in就是多个or的集合 ,(not in 不在这个范围中)
mysql> select empno,ename,job from emp where job in('MANAGER', 'SALESMAN');
+-------+--------+----------+
| empno | ename | job |
+-------+--------+----------+
| 7499 | ALLEN | SALESMAN |
| 7521 | WARD | SALESMAN |
| 7566 | JONES | MANAGER |
| 7654 | MARTIN | SALESMAN |
| 7698 | BLAKE | MANAGER |
| 7782 | CLARK | MANAGER |
| 7844 | TURNER | SALESMAN |
+-------+--------+----------+
7 rows in set (0.00 sec)
mysql> select ename,sal from emp where sal in(800, 5000);# 只会找到sal=500和sal=5000的信息
+-------+---------+
| ename | sal |
+-------+---------+
| SMITH | 800.00 |
| KING | 5000.00 |
+-------+---------+
2 rows in set (0.00 sec)
括号里面的值不能理解成区间范围,只能理解成可选项。
like % _
模糊查找
%
表示若干个字符,_
表示一个字符,如果查找的字符串中含有这两个关键字符,需要用转义字符\
例如:查找名字以T结尾的成员信息
mysql> select ename from emp where ename like '%T';
+-------+
| ename |
+-------+
| SCOTT |
+-------+
1 row in set (0.00 sec)
排序
查询所有员工薪资,排序?
按照一个字段排序
select 字段名1,字段名2,...
from 表名
order by 字段名;
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 |
| SCOTT | 3000.00 |
| FORD | 3000.00 |
| KING | 5000.00 |
+--------+---------+
14 rows in set (0.00 sec)
通过发现可以知道默认是从上到下,升序排列
指定降序和升序排列
- 降序
select 字段名1,字段名2,...
from 表名
order by 字段名 desc;
- 升序
select 字段名1,字段名2,...
from 表名
order by 字段名 asc;
关键字asc
和desc
分别代表ascend
和descend
,帮助记忆。
按照多个字段排序
select 字段名1,字段名2,...
from 表名
order by 字段名1 asc/desc,字段名2 asc/desc ...;
# 如果按照字段名1进行排序遇到相等的情况,就按照字段名2进行排序
比如说:
查询员工名字和薪资,要求按照薪资升序,如果薪资一样的话,再按照名字升序排列。
mysql> select-> ename,sal-> from-> emp-> order by-> sal asc, ename asc;
+--------+---------+
| ename | sal |
+--------+---------+
| SMITH | 800.00 |
| JAMES | 950.00 |
| ADAMS | 1100.00 |
| MARTIN | 1250.00 |
| WARD | 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 |
+--------+---------+
14 rows in set (0.00 sec)
mysql> select-> ename,sal-> from-> emp-> order by-> sal asc, ename asc;# sal在前,起主导,只有sal相等的时候,才会考虑启用ename排序。
综合测试:找出工资在1250到3000之间的员工信息,要求按照薪资降序排列。
mysql> select ename,sal-> from emp-> where sal>=1250 and sal<=3000-> order by-> sal desc;
+--------+---------+
| ename | sal |
+--------+---------+
| SCOTT | 3000.00 |
| FORD | 3000.00 |
| JONES | 2975.00 |
| BLAKE | 2850.00 |
| CLARK | 2450.00 |
| ALLEN | 1600.00 |
| TURNER | 1500.00 |
| MILLER | 1300.00 |
| WARD | 1250.00 |
| MARTIN | 1250.00 |
+--------+---------+
10 rows in set (0.01 sec)
注意:
关键字顺序不能变:select...from...where...order by... ;
以上语句的执行顺序必须掌握:
第一步:from
第二步:where
第三步:select
第四步:order by(排序总是在最后执行!)
数据处理函数/单行处理函数
也被称为单行处理函数:一个输入对应一个输出。
lower转小写
mysql> select lower(ename) from emp;
# 这里也可以取别名
# select lower(ename) as ename from emp;
+--------------+
| lower(ename) |
+--------------+
| smith |
| allen |
| ward |
| jones |
| martin |
| blake |
| clark |
| scott |
| king |
| turner |
| adams |
| james |
| ford |
| miller |
+--------------+
14 rows in set (0.01 sec)--------------------------------
mysql> select lower(ename) as ename,lower(Job) as job from emp;# 也可以处理多列
+--------+-----------+
| ename | job |
+--------+-----------+
| smith | clerk |
| allen | salesman |
| ward | salesman |
| jones | manager |
| martin | salesman |
| blake | manager |
| clark | manager |
| scott | analyst |
| king | president |
| turner | salesman |
| adams | clerk |
| james | clerk |
| ford | analyst |
| miller | clerk |
+--------+-----------+
14 rows in set (0.00 sec)
upper转大写
和小写一个用法
substr提取子串
substr(被截取的字符串,起始下标,截取的长度)
注意,SQL语句中的下标是从1
开始的
例如,我们用substr提取出字符串中的首字母来判断首字母是不是‘A’,并且将相关信息提取出来。
mysql> select ename ,job,sal from emp where substr(ename,1,1)='A';
+-------+----------+---------+
| ename | job | sal |
+-------+----------+---------+
| ALLEN | SALESMAN | 1600.00 |
| ADAMS | CLERK | 1100.00 |
+-------+----------+---------+
2 rows in set (0.01 sec)
concat拼接字符串
mysql> select concat(empno,ename,job) from emp;# 这里发现是可以拼接多个字符串的
+-------------------------+
| concat(empno,ename,job) |
+-------------------------+
| 7369SMITHCLERK |
| 7499ALLENSALESMAN |
| 7521WARDSALESMAN |
| 7566JONESMANAGER |
| 7654MARTINSALESMAN |
| 7698BLAKEMANAGER |
| 7782CLARKMANAGER |
| 7788SCOTTANALYST |
| 7839KINGPRESIDENT |
| 7844TURNERSALESMAN |
| 7876ADAMSCLERK |
| 7900JAMESCLERK |
| 7902FORDANALYST |
| 7934MILLERCLERK |
+-------------------------+
14 rows in set (0.00 sec)
length取长度
mysql> select length(ename) enamelength from emp;
+-------------+
| enamelength |
+-------------+
| 5 |
| 5 |
| 4 |
| 5 |
| 6 |
| 5 |
| 5 |
| 5 |
| 4 |
| 6 |
| 5 |
| 5 |
| 4 |
| 6 |
+-------------+
14 rows in set (0.00 sec)
trim去空格
也是去除字符串的前后空白
mysql> select * from emp where ename=trim(' KING ');
+-------+-------+-----------+------+------------+---------+------+--------+
| EMPNO | ENAME | JOB | MGR | HIREDATE | SAL | COMM | DEPTNO |
+-------+-------+-----------+------+------------+---------+------+--------+
| 7839 | KING | PRESIDENT | NULL | 1981-11-17 | 5000.00 | NULL | 10 |
+-------+-------+-----------+------+------------+---------+------+--------+
1 row in set (0.00 sec)
但是
mysql> select * from emp where ename=trim(' K I NG ');
Empty set (0.00 sec)
这样是查询不到的。
round四舍五入
select 'abc' from emp; // select后面直接跟“字面量/字面值”
mysql> select 'abc' from emp;
+-----+
| abc |
+-----+
| abc |
| abc |
| abc |
| abc |
| abc |
| abc |
| abc |
| abc |
| abc |
| abc |
| abc |
| abc |
| abc |
| abc |
+-----+mysql> select abc from emp;ERROR 1054 (42S22): Unknown column 'abc' in 'field list'这样肯定报错,因为会把abc当做一个字段的名字,去emp表中找abc字段去了。select 1000 as num from emp; // 1000 也是被当做一个字面量/字面值。+------+| num |+------+| 1000 || 1000 || 1000 || 1000 || 1000 || 1000 || 1000 || 1000 || 1000 || 1000 || 1000 || 1000 || 1000 || 1000 |+------+
结论:select后面可以跟某个表的字段名(可以等同看做变量名),也可以跟字面量/字面值(数据)。
select round(1245.6735,0) as num from emp;# 将1245.6735保留到整数位
+------+
| num |
+------+
| 1246 |
| 1246 |
| 1246 |
| 1246 |
| 1246 |
| 1246 |
| 1246 |
| 1246 |
| 1246 |
| 1246 |
| 1246 |
| 1246 |
| 1246 |
| 1246 |
+------+
select round(1245.6735,1) as num from emp;# 保留一位小数
+--------+
| num |
+--------+
| 1245.7 |
| 1245.7 |
| 1245.7 |
| 1245.7 |
| 1245.7 |
| 1245.7 |
| 1245.7 |
| 1245.7 |
| 1245.7 |
| 1245.7 |
| 1245.7 |
| 1245.7 |
| 1245.7 |
| 1245.7 |
+--------+
依次类推
select round(1245.6735,-1) as num from emp;# -1那么就是保留到十位
+------+
| num |
+------+
| 1250 |
| 1250 |
| 1250 |
| 1250 |
| 1250 |
| 1250 |
| 1250 |
| 1250 |
| 1250 |
| 1250 |
| 1250 |
| 1250 |
| 1250 |
| 1250 |
+------+
rand生成随机数
mysql> select rand() as random from emp;
+---------------------+
| random |
+---------------------+
| 0.6779789288323176 |
| 0.03282456009911798 |
| 0.13018604473228199 |
| 0.552456574097701 |
| 0.3717247670253038 |
| 0.20125414356706117 |
| 0.8910964474930395 |
| 0.8517198374976589 |
| 0.5853098757428209 |
| 0.3713898969547729 |
| 0.10101988827904676 |
| 0.3909297812645601 |
| 0.6515892722193052 |
| 0.08515704803649062 |
+---------------------+
可以结合round函数生成整数随机数
mysql> select round(rand()*100,0) as random from emp;# 生成100以内的随机数
+--------+
| random |
+--------+
| 47 |
| 10 |
| 9 |
| 13 |
| 38 |
| 50 |
| 39 |
| 42 |
| 95 |
| 47 |
| 52 |
| 20 |
| 43 |
| 53 |
+--------+
ifnull 处理null值
在SQL语句中规定,所有数据与null进行数学运算之后的结果只能是null
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 |
+-------+--------+-----------+------+------------+---------+---------+--------+
14 rows in set (0.00 sec)mysql> select ename,sal+comm as salcomm from emp;# 会发现所有sal中的数据加上null都变成了null;
+--------+---------+
| ename | salcomm |
+--------+---------+
| SMITH | NULL |
| ALLEN | 1900.00 |
| WARD | 1750.00 |
| JONES | NULL |
| MARTIN | 2650.00 |
| BLAKE | NULL |
| CLARK | NULL |
| SCOTT | NULL |
| KING | NULL |
| TURNER | 1500.00 |
| ADAMS | NULL |
| JAMES | NULL |
| FORD | NULL |
| MILLER | NULL |
+--------+---------+
但是有时候我们并不想这么做,我们认为有时候null代表着0,那么这个时候该怎么做呢?
使用ifnull
函数ifnull(数据,null被当作哪个值)
mysql> select ename,sal+ifnull(comm,0) as salcomm from emp;# 这里我们将null当作0
+--------+---------+
| ename | salcomm |
+--------+---------+
| SMITH | 800.00 |
| ALLEN | 1900.00 |
| WARD | 1750.00 |
| JONES | 2975.00 |
| MARTIN | 2650.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 |
+--------+---------+
case…when…then…when…then…else…end模拟if-else语句
当员工的工作岗位是MANAGER的时候,工资上调10%,当工作岗位是SALESMAN的时候,工资上调50%,其它正常。
(注意:不修改数据库,只是将查询结果显示为工资上调)
case(变量)when(变量满足条件1)then(如果满足条件1后的执行)when(变量满足条件2)then...else...end
select ename,job,sal as oldsal,(case job when 'MANAGER' then sal*1.1 when 'SALESMAN' then sal*1.5 else sal end) as newsalfrom emp;
+--------+-----------+---------+---------+
| ename | job | oldsal | newsal |
+--------+-----------+---------+---------+
| SMITH | CLERK | 800.00 | 800.00 |
| ALLEN | SALESMAN | 1600.00 | 2400.00 |
| WARD | SALESMAN | 1250.00 | 1875.00 |
| JONES | MANAGER | 2975.00 | 3272.50 |
| MARTIN | SALESMAN | 1250.00 | 1875.00 |
| BLAKE | MANAGER | 2850.00 | 3135.00 |
| CLARK | MANAGER | 2450.00 | 2695.00 |
| SCOTT | ANALYST | 3000.00 | 3000.00 |
| KING | PRESIDENT | 5000.00 | 5000.00 |
| TURNER | SALESMAN | 1500.00 | 2250.00 |
| ADAMS | CLERK | 1100.00 | 1100.00 |
| JAMES | CLERK | 950.00 | 950.00 |
| FORD | ANALYST | 3000.00 | 3000.00 |
| MILLER | CLERK | 1300.00 | 1300.00 |
+--------+-----------+---------+---------+
14 rows in set (0.00 sec)
str_to_date
将字符串varchar类型转换成date类型。
date_format
将date类型转换成具有一定格式的varchar字符串类型。
分组函数/多行处理函数
输入多行,输出一行。
- count 计数
- sum 求和
- avg 平均值
- max 最大值
- min 最小值
注意:
分组函数在使用的时候必须先进行分组,然后才能用。
如果你没有对数据进行分组,整张表默认为一组。
mysql> select max(sal) from emp;# 求最大值
+----------+
| max(sal) |
+----------+
| 5000.00 |
+----------+
1 row in set (0.01 sec)mysql> select min(sal) from emp;# 求最小值
+----------+
| min(sal) |
+----------+
| 800.00 |
+----------+
1 row in set (0.01 sec)mysql> select avg(sal) from emp;# 求平均值
+-------------+
| avg(sal) |
+-------------+
| 2073.214286 |
+-------------+
1 row in set (0.00 sec)mysql> select sum(sal) from emp;# 求总和
+----------+
| sum(sal) |
+----------+
| 29025.00 |
+----------+
1 row in set (0.00 sec)mysql> select count(sal) from emp;# 求个数
+------------+
| count(sal) |
+------------+
| 14 |
+------------+
1 row in set (0.00 sec)
值得注意的是分组函数有几个注意事项
- 分组函数自动忽略掉
null
值,我们不需要提前对null
值进行处理,例如:
mysql> select count(comm) from emp;
+-------------+
| count(comm) |
+-------------+
| 4 |
+-------------+
- 分组函数中
count(*)
与count(具体字段)
的区别
count(*)
会统计表中的总行数。
count(具体字段)
会忽略字段中的null
。
因为每一行记录不可能都为NULL,一行数据中有一列不为NULL,则这行数据就是有效的。
- 分组函数不能用在
where
子句中(分组查询中会解释)
select ename,job,sal from emp where max(sal);
ERROR 1111 (HY000): Invalid use of group function
- 所有的分组函数可以组合在一起用
mysql> select sum(sal),min(sal),max(sal),avg(sal),count(*) from emp;
+----------+----------+----------+-------------+----------+
| sum(sal) | min(sal) | max(sal) | avg(sal) | count(*) |
+----------+----------+----------+-------------+----------+
| 29025.00 | 800.00 | 5000.00 | 2073.214286 | 14 |
+----------+----------+----------+-------------+----------+
1 row in set (0.00 sec)
分组查询
在实际的应用中,可能有这样的需求,需要先进行分组,然后对每一组的数据进行操作。
例如我们要计算每个部门的薪资和,每个工作岗位的平均薪资,这都是要进行分组,分组之后才能计算
select...from...group by...
结合已经学到的关键字,可以知道有代码顺序:
select
...
from
...
where
...
group by
...
order by
...
上面的执行顺序应该是
- from
- where
- group by
- select
- order by
结合分组函数的使用注意事项分组函数必须先分组,才能执行,那么where
子句中如果有分组函数,但是group by
是在where
语句执行完之后才会执行的,因此执行where
语句中的分组函数,那个时候是还没有完成分组的,于是就会报错。
单个分组
找出每个工作岗位的工资和。
select job,sum(sal)
fromemp
group byjob;+-----------+----------+
| job | sum(sal) |
+-----------+----------+
| CLERK | 4150.00 |
| SALESMAN | 5600.00 |
| MANAGER | 8275.00 |
| ANALYST | 6000.00 |
| PRESIDENT | 5000.00 |
+-----------+----------+
那么上面的代码中select
后面还能加上别的字段名吗?
答案是不可以的,那样会报错。如果想要找出每个工作岗位的工资最高的人是谁,显示名字啥的,需要结合后面学习到的知识才能运行。
在有的时候,上面说的情况不会报错,但是那样是没有意义的。
重点结论:
在一条select语句当中,如果有group by语句的话,
select后面只能跟:参加分组的字段,以及分组函数。
其它的一律不能跟。
多个分组
找出“每个部门,不同工作岗位”的最高薪资
mysql> select-> deptno,job,max(sal)-> from-> emp-> group by-> deptno,job# 根据多个选项进行分组-> order by-> deptno;
+--------+-----------+----------+
| 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 |
+--------+-----------+----------+
9 rows in set (0.00 sec)
having语句进行进一步过滤
找出每个部门最高薪资,要求显示最高薪资大于3000的?
首先我们找到每个部门的最高薪资
mysql> select deptno,max(sal) from emp group by deptno;
+--------+----------+
| deptno | max(sal) |
+--------+----------+
| 20 | 3000.00 |
| 30 | 2850.00 |
| 10 | 5000.00 |
+--------+----------+
然后我们再对最高薪资进行过滤
mysql> select deptno,max(sal) from emp group by deptno having max(sal)>3000;
+--------+----------+
| deptno | max(sal) |
+--------+----------+
| 10 | 5000.00 |
+--------+----------+
思考:这样做效率是不是很低?
实际上我们可以先把所有大于3000的人找出来再分组
mysql> select deptno,max(sal) from emp where sal>3000 group by deptno;
+--------+----------+
| deptno | max(sal) |
+--------+----------+
| 10 | 5000.00 |
+--------+----------+
但是有的时候也会存在where无法过滤的情况
找出每个部门平均薪资,要求显示平均薪资高于2500的。
这个例子中,我们就必须先找出平均薪资了,是无法用where过滤的
mysql> select deptno,avg(sal) from emp group by deptno having avg(sal)>2500;
+--------+-------------+
| deptno | avg(sal) |
+--------+-------------+
| 10 | 2916.666667 |
+--------+-------------+
distinct关键字
distinct
关键字是用来对查询记录进行重复处理
mysql> select job from emp;
+-----------+
| job |
+-----------+
| CLERK |
| SALESMAN |
| SALESMAN |
| MANAGER |
| SALESMAN |
| MANAGER |
| MANAGER |
| ANALYST |
| PRESIDENT |
| SALESMAN |
| CLERK |
| CLERK |
| ANALYST |
| CLERK |
+-----------+
例如这里查询job
字段,会有重复的job出现,这个时候可以用distinct
关键字进行去重
mysql> select distinct job from emp;
+-----------+
| job |
+-----------+
| CLERK |
| SALESMAN |
| MANAGER |
| ANALYST |
| PRESIDENT |
+-----------+
注意:distinct
关键字只能出现在字段名之前,不能夹在字段名中间。
mysql> select ename,distinct job from emp;
这样是错误的。
当distinct
关键字后面有多个字段名的时候,它会实现联合这多个字段名进行查询结果的去重。
mysql> select deptno,job from emp;
+--------+-----------+
| deptno | job |
+--------+-----------+
| 20 | CLERK |
| 30 | SALESMAN |
| 30 | SALESMAN |
| 20 | MANAGER |
| 30 | SALESMAN |
| 30 | MANAGER |
| 10 | MANAGER |
| 20 | ANALYST |
| 10 | PRESIDENT |
| 30 | SALESMAN |
| 20 | CLERK |
| 30 | CLERK |
| 20 | ANALYST |
| 10 | CLERK |
+--------+-----------+
mysql> select distinct deptno,job from emp;
+--------+-----------+
| deptno | job |
+--------+-----------+
| 20 | CLERK |
| 30 | SALESMAN |
| 20 | MANAGER |
| 30 | MANAGER |
| 10 | MANAGER |
| 20 | ANALYST |
| 10 | PRESIDENT |
| 30 | CLERK |
| 10 | CLERK |
+--------+-----------+
统计job的种类数量:
mysql> select count(distinct job) from emp;
+---------------------+
| count(distinct job) |
+---------------------+
| 5 |
+---------------------+
小结
select ...from...where...group by...having...order by...
上面是已经学到的整个框架,顺序是不能变的。
执行顺序大概是:
from
从某张表中查询数据where
先经过where条件筛选出有价值的数据。group by
对这些有价值的数据进行分组。having
分组之后可以使用having继续筛选。select
使用select查询出来。order by
最后排序输出!
找出每个岗位的平均薪资,要求显示平均薪资大于1500的,除MANAGER岗位之外,要求按照平均薪资降序排。
mysql> select job ,avg(sal) as avgsalfrom empwhere job!='MANAGER'group by jobhavingavg(sal)>1500order by avgsal desc;
+-----------+-------------+
| job | avgsal |
+-----------+-------------+
| PRESIDENT | 5000.000000 |
| ANALYST | 3000.000000 |
+-----------+-------------+
连接查询
从一张表中单独查询,称为单表查询。
emp表和dept表联合起来查询数据,从emp表中取员工名字,从dept表中取部门名字。
这种跨表查询,多张表联合起来查询数据,被称为连接查询。
根据表连接的方式分类:
内连接:
等值连接
非等值连接
自连接 外连接:
左外连接(左连接)
右外连接(右连接) 全连接
笛卡尔积现象
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 |
+-------+--------+-----------+------+------------+---------+---------+--------+
14 rows in set (0.00 sec)mysql> select * from dept;
+--------+------------+----------+
| DEPTNO | DNAME | LOC |
+--------+------------+----------+
| 10 | ACCOUNTING | NEW YORK |
| 20 | RESEARCH | DALLAS |
| 30 | SALES | CHICAGO |
| 40 | OPERATIONS | BOSTON |
+--------+------------+----------+
4 rows in set (0.00 sec)
当两张表进行无条件的连接查询:
mysql> select ename,dname from emp,dept;
+--------+------------+
| ename | dname |
+--------+------------+
| SMITH | OPERATIONS |
| SMITH | SALES |
| SMITH | RESEARCH |
| SMITH | ACCOUNTING |
| ALLEN | OPERATIONS |
| ALLEN | SALES |
| ALLEN | RESEARCH |
| ALLEN | ACCOUNTING |
| WARD | OPERATIONS |
| WARD | SALES |
| WARD | RESEARCH |
| WARD | ACCOUNTING |
| JONES | OPERATIONS |
| JONES | SALES |
| JONES | RESEARCH |
| JONES | ACCOUNTING |
| MARTIN | OPERATIONS |
| MARTIN | SALES |
| MARTIN | RESEARCH |
| MARTIN | ACCOUNTING |
| BLAKE | OPERATIONS |
| BLAKE | SALES |
| BLAKE | RESEARCH |
| BLAKE | ACCOUNTING |
| CLARK | OPERATIONS |
| CLARK | SALES |
| CLARK | RESEARCH |
| CLARK | ACCOUNTING |
| SCOTT | OPERATIONS |
| SCOTT | SALES |
| SCOTT | RESEARCH |
| SCOTT | ACCOUNTING |
| KING | OPERATIONS |
| KING | SALES |
| KING | RESEARCH |
| KING | ACCOUNTING |
| TURNER | OPERATIONS |
| TURNER | SALES |
| TURNER | RESEARCH |
| TURNER | ACCOUNTING |
| ADAMS | OPERATIONS |
| ADAMS | SALES |
| ADAMS | RESEARCH |
| ADAMS | ACCOUNTING |
| JAMES | OPERATIONS |
| JAMES | SALES |
| JAMES | RESEARCH |
| JAMES | ACCOUNTING |
| FORD | OPERATIONS |
| FORD | SALES |
| FORD | RESEARCH |
| FORD | ACCOUNTING |
| MILLER | OPERATIONS |
| MILLER | SALES |
| MILLER | RESEARCH |
| MILLER | ACCOUNTING |
+--------+------------+
56 rows in set (0.01 sec)
我们发现,他其实是拿emp表中的每个成员分别和dept中的四个成员连接,最终也就是有了4*14
行的数据了,但是这里面有一些数据是没有意义的,因为我们连接两个表进行查询是为了通过两个表具有相同的元素进行关联查询,即通过deptno
关联起来两个表,但是结果是具有冗余数据的,这种现象就是笛卡尔积现象。
避免笛卡尔积现象
连接时加条件,满足这个条件的记录被筛选出来!
selectename,dname# 它既会去emp中找ename也会去dept中找ename(dname)同理,因此效率并不是很高# 提高效率可以这样写:emp.ename,dept.dname
from emp,dept
where emp.deptno=dept.deptno;+--------+------------+
| ename | dname |
+--------+------------+
| SMITH | RESEARCH |
| ALLEN | SALES |
| WARD | SALES |
| JONES | RESEARCH |
| MARTIN | SALES |
| BLAKE | SALES |
| CLARK | ACCOUNTING |
| SCOTT | RESEARCH |
| KING | ACCOUNTING |
| TURNER | SALES |
| ADAMS | RESEARCH |
| JAMES | SALES |
| FORD | RESEARCH |
| MILLER | ACCOUNTING |
+--------+------------+
这样就能实现两个表通过deptno产生关联,连接之后再进行查询。
最终查询的结果条数是14条,但是匹配的过程中,匹配的次数减少了吗?
还是56次,只不过进行了四选一。次数没有减少。注意:通过笛卡尔积现象得出,表的连接次数越多效率越低,尽量避免表的
连接次数。
同时一种书写习惯是,给表取别名
# 表起别名。很重要。效率问题。select e.ename,d.dname from emp e, dept dwheree.deptno = d.deptno; //SQL92语法。
内连接与等值连接
条件是等量关系,所以被称为等值连接。
# SQL92语法。
select e.ename,d.dname from emp e, dept dwheree.deptno = d.deptno;
sql92的缺点:结构不清晰,表的连接条件,和后期进一步筛选的条件,都放到了where后面。
# SQL99语法
select e.ename,d.dnamefromemp einner join #inner可以省略(带着inner可读性更好!!!一眼就能看出来是内连接)dept done.deptno = d.deptno;# 条件是等量关系,所以被称为等值连接。
sql99优点:表连接的条件是独立的,连接之后,如果还需要进一步筛选,再往后继续添加where。
# SQL99语法:select ...fromajoinbona和b的连接条件where筛选条件
内连接与非等值连接
条件不是一个等量关系,称为非等值连接。
案例:找出每个员工的薪资等级,要求显示员工名、薪资、薪资等级?
mysql> select * from salgrade;
+-------+-------+-------+
| GRADE | LOSAL | HISAL |
+-------+-------+-------+
| 1 | 700 | 1200 |
| 2 | 1201 | 1400 |
| 3 | 1401 | 2000 |
| 4 | 2001 | 3000 |
| 5 | 3001 | 9999 |
+-------+-------+-------+
mysql> select-> e.ename,e.sal,s.grade-> from-> emp e-> join-> salgrade s-> on-> e.sal >= s.losal and e.sal <=s.hisal;# emp表中的薪资在salgrade表中的区间范围之内的# 条件不是一个等量关系,称为非等值连接。
+--------+---------+-------+
| 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 |
+--------+---------+-------+
内连接与自然连接
案例:查询员工的上级领导,要求显示员工名和对应的领导名?
员工名和领导名的相关信息都是在同一个表中,技巧就是将emp a看作员工表,将emp b看作领导表,然后将这两个表进行等值连接
mysql> select empno,ename,mgr from 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 |
+-------+--------+------+
empno
是员工编号,mgt
是员工对应的领导的编号。
select a.ename as '员工',b.ename as '领导'
fromemp a
join emp b
ona.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 rows in set (0.00 sec)
由于KING
没有领导,因此没有这个人的数据,一共只有13行数据。
技巧:一张表看做两张表。
外连接与左外连接右外连接
内连接所连接查询的表没有主次关系,不能全部都匹配出来(比如上方的那个KING
案例,就没有匹配到他的领导)
外连接是具有主次关系的,关键字:right/left
右外连接
select e.ename,d.dname
fromemp e
right outer join # outer是可以省略的,带着可读性强。dept d
one.deptno = d.deptno;# 完全根据这个条件进行匹配
+--------+------------+
| ename | dname |
+--------+------------+
| MILLER | ACCOUNTING |
| KING | ACCOUNTING |
| CLARK | ACCOUNTING |
| FORD | RESEARCH |
| ADAMS | RESEARCH |
| SCOTT | RESEARCH |
| JONES | RESEARCH |
| SMITH | RESEARCH |
| JAMES | SALES |
| TURNER | SALES |
| BLAKE | SALES |
| MARTIN | SALES |
| WARD | SALES |
| ALLEN | SALES |
| NULL | OPERATIONS |
+--------+------------+
会发现最底下会有NULL,这是因为d表中有的值在e表中是无法匹配到相关数据的。
right
表示在join
右边的这张表看作主表,主表中的所有数据都要在另一个表中关于on中的条件进行查询,如果没有找到可以匹配的,就用NULL
代替。
左外连接
select e.ename,d.dname
fromdept d
left join emp e
one.deptno = d.deptno;
+--------+------------+
| ename | dname |
+--------+------------+
| MILLER | ACCOUNTING |
| KING | ACCOUNTING |
| CLARK | ACCOUNTING |
| FORD | RESEARCH |
| ADAMS | RESEARCH |
| SCOTT | RESEARCH |
| JONES | RESEARCH |
| SMITH | RESEARCH |
| JAMES | SALES |
| TURNER | SALES |
| BLAKE | SALES |
| MARTIN | SALES |
| WARD | SALES |
| ALLEN | SALES |
| NULL | OPERATIONS |
+--------+------------+
在join
关键字左边的表作为主表,将主表中的所有数据进行查询
带有right的是右外连接,又叫做右连接。
带有left的是左外连接,又叫做左连接。
任何一个右连接都有左连接的写法。
任何一个左连接都有右连接的写法。
内连接与外连接主要区别在于:
内连接所关联的的表之间是没有主次关系的,当一个表中的数据在另一个表中的没有相关联的,就不会进行查询匹配。
外连接所关联的表之间是有主次关系的,关键字right/left
用来标记关键字join
旁的哪个表作为主表,主表中的所有数据都必须进行查询,若没有相关联的匹配项就用null代替。
mysql> selecta.ename as '员工',b.ename as '领导'fromemp aleft joinemp bona.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 |
+--------+--------+
多表连接
语法:select ...fromajoinbona和b的连接条件joincona和c的连接条件right joindona和d的连接条件
一个SQL语句中内连接和外连接可以混合使用。
案例:找出每个员工的部门名称以及工资等级,要求显示员工名、部门名、薪资、薪资等级?
selecte.ename,d.dname,e.sal,s.grade
fromemp e
joindept d
one.deptno=d.deptno
joinsalgrade s
on e.sal between s.losal and hisal
order bye.sal;
+--------+------------+---------+-------+
| ename | dname | sal | grade |
+--------+------------+---------+-------+
| SMITH | RESEARCH | 800.00 | 1 |
| JAMES | SALES | 950.00 | 1 |
| ADAMS | RESEARCH | 1100.00 | 1 |
| WARD | SALES | 1250.00 | 2 |
| MARTIN | SALES | 1250.00 | 2 |
| MILLER | ACCOUNTING | 1300.00 | 2 |
| TURNER | SALES | 1500.00 | 3 |
| ALLEN | SALES | 1600.00 | 3 |
| CLARK | ACCOUNTING | 2450.00 | 4 |
| BLAKE | SALES | 2850.00 | 4 |
| JONES | RESEARCH | 2975.00 | 4 |
| SCOTT | RESEARCH | 3000.00 | 4 |
| FORD | RESEARCH | 3000.00 | 4 |
| KING | ACCOUNTING | 5000.00 | 5 |
+--------+------------+---------+-------+
14 rows in set (0.00 sec)
结合外连接,将每个员工的上司也输出
selecte.ename '员工',d.dname,m.ename '上司',e.sal,s.grade
fromemp e
joindept d
one.deptno=d.deptno
joinsalgrade s
on e.sal between s.losal and hisal
left joinemp m
one.mgr=m.empno
order bye.sal;
+--------+------------+--------+---------+-------+
| 员工 | dname | 上司 | sal | grade |
+--------+------------+--------+---------+-------+
| SMITH | RESEARCH | FORD | 800.00 | 1 |
| JAMES | SALES | BLAKE | 950.00 | 1 |
| ADAMS | RESEARCH | SCOTT | 1100.00 | 1 |
| MARTIN | SALES | BLAKE | 1250.00 | 2 |
| WARD | SALES | BLAKE | 1250.00 | 2 |
| MILLER | ACCOUNTING | CLARK | 1300.00 | 2 |
| TURNER | SALES | BLAKE | 1500.00 | 3 |
| ALLEN | SALES | BLAKE | 1600.00 | 3 |
| CLARK | ACCOUNTING | KING | 2450.00 | 4 |
| BLAKE | SALES | KING | 2850.00 | 4 |
| JONES | RESEARCH | KING | 2975.00 | 4 |
| FORD | RESEARCH | JONES | 3000.00 | 4 |
| SCOTT | RESEARCH | JONES | 3000.00 | 4 |
| KING | ACCOUNTING | NULL | 5000.00 | 5 |
+--------+------------+--------+---------+-------+
14 rows in set (0.00 sec)
子查询
select语句中嵌套select语句,被嵌套的select语句称为子查询。
select..(select).from..(select).where..(select).
where子查询
案例:找出比最低工资高的员工姓名和工资?
select ename,sal from emp where sal>min(sal);
这个句子是错误的,因为分组函数不能出现在where
之中。
第一步:查询最低工资是多少
mysql> select min(sal) from emp;
+----------+
| min(sal) |
+----------+
| 800.00 |
+----------+
第二步:找到>800的人
mysql> select ename,sal from emp where sal>800;
+--------+---------+
| ename | sal |
+--------+---------+
| 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 |
+--------+---------+
第三步:合并
select ename,sal
from emp
wheresal>(select min(sal) from emp);
执行到where
会先去执行子查询,得到最小值,然后执行where
中的判断语句。
from子查询
在from后面的子查询所得到的结果可以看作一张临时表。
案例:找出每个岗位的平均工资的薪资等级。
第一步:找到每个岗位的平均薪资(分组查询)
mysql> select job,avg(sal) from emp group by job;
+-----------+-------------+
| job | avg(sal) |
+-----------+-------------+
| CLERK | 1037.500000 |
| SALESMAN | 1400.000000 |
| MANAGER | 2758.333333 |
| ANALYST | 3000.000000 |
| PRESIDENT | 5000.000000 |
+-----------+-------------+
第二步:将上述表看作一张临时表,与工资等级表进行连接
select t.job,t.avgsal,s.grade
from (select job,avg(sal) as avgsal from emp group by job) t
joinsalgrade s
ont.avgsal between s.losal and s.hisal;
+-----------+-------------+-------+
| job | avgsal | grade |
+-----------+-------------+-------+
| CLERK | 1037.500000 | 1 |
| SALESMAN | 1400.000000 | 2 |
| MANAGER | 2758.333333 | 4 |
| ANALYST | 3000.000000 | 4 |
| PRESIDENT | 5000.000000 | 5 |
+-----------+-------------+-------+
select子查询
mysql> selecte.ename,e.deptno,(select d.dname from dept d where e.deptno = d.deptno) as dnamefromemp e;
+--------+--------+------------+
| ename | deptno | dname |
+--------+--------+------------+
| SMITH | 20 | RESEARCH |
| ALLEN | 30 | SALES |
| WARD | 30 | SALES |
| JONES | 20 | RESEARCH |
| MARTIN | 30 | SALES |
| BLAKE | 30 | SALES |
| CLARK | 10 | ACCOUNTING |
| SCOTT | 20 | RESEARCH |
| KING | 10 | ACCOUNTING |
| TURNER | 30 | SALES |
| ADAMS | 20 | RESEARCH |
| JAMES | 30 | SALES |
| FORD | 20 | RESEARCH |
| MILLER | 10 | ACCOUNTING |
+--------+--------+------------+
14 rows in set (0.00 sec)
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 |
+--------+----------+
union主要体现在合并表的效率很高,在表连接中,每次连接一次新的表,匹配的次数就会乘以新表的行数
但是使用union可以减少匹配的次数,并且完成表的拼接
a 连接 b 连接 c
a 10条记录
b 10条记录
c 10条记录
匹配次数是:1000=10*10*10
使用union的话是:
a连接b:10*10uniona连接c:10*10100次 + 100次 = 200次。
使用union
的一写注意事项:
-
要求合并的两个表的列数相同
-
要求合并的两个表的列与列之间的数据类型一致
-
注释:UNION 结果集中的列名总是等于 UNION 中第一个 SELECT 语句中的列名。
-
union会自动删除重复行,union all 则不会
limit分页
limit startIndex, length
通过limit去除表中的一部分数据,提高用户的的体验
startIndex
默认是从0开始的
省缺用法:
limit 5;
取出前5条数据。
selectename,sal
from emp
order bysal desc
limit 5;
+-------+---------+
| ename | sal |
+-------+---------+
| KING | 5000.00 |
| SCOTT | 3000.00 |
| FORD | 3000.00 |
| JONES | 2975.00 |
| BLAKE | 2850.00 |
+-------+---------+
这样就找到了前5条
limit 2,3;# 表示从下标2开始,也就是第三条数据开始,取出3条数据,也就是第3,4,5
公式:
每页显示pageSize
条记录:
第pageNo
页:limit (pageNo - 1) * pageSize , pageSize
相关文章:

MySql学习笔记03——DQL(数据查询)基本命令
DQL 导入数据 首先使用use database进入数据库中,然后使用命令 source D:\mysql_learning\mysql_learning\document\bjpowernode.sql注意文件名不能有双引号,命令结尾没有分号。 SQL脚本 .sql文件是SQL脚本文件,它里面的内容都是SQL语句…...

操作系统的四大特性
一、并发性 指操作系统同时运行着多个程序,这些程序宏观上是同时运行的,但微观上其实是交替运行的 补充1:并发性区别于并行性 并发是指两个或多个事件在同一时间间隔内发生,事件宏观上是同时进行的,围观上市交替进行的…...

旅游攻略APP外包开发功能
旅游攻略APP是帮助旅行者计划和享受旅行的工具,下面列出了一些常见的旅游攻略APP功能,以及在上线这类应用时需要注意的问题,希望对大家有所帮助。北京木奇移动技术有限公司,专业的软件外包开发公司,欢迎交流合作。 常见…...

Apollo在Java中的使用
本节主要讲解在普通的 Java 项目和 Spring Boot 中如何使用 Apollo。 普通 Java 项目中使用 加入 Apollo Client 的 Maven 依赖,代码如下所示。 <dependency><groupId>com.ctrip.framework.apollo</groupId><artifactId>apollo-client<…...

Elasticsearch 全文搜索引擎 ---- IK分词器
原理:分词的原理:二叉树 首先讲一下为什么要出这个文章,前面我们讲过分词方法:中文分词搜索 pscws(感兴趣的同学可以去爬楼看一下),那为什么要讲IK分词?最主要的原因是&…...

Layer 2盛夏已至,StarkNet如何实现价值跃迁?
作者|Jason Jiang Layer 2概念在2023年夏天迎来爆发。Coinbase、ConsenSys等加密巨头纷纷下场,其部署的原生L2解决方案Base、Linea在过去两个月内相继完成主网上线;被誉为L2 四大天王之一的StarkNet也在夏天顺利完成“量子跃迁”升级&#x…...

KaiwuDB 受邀亮相 2023 中国国际“软博会”
8月31日,第二十五届中国国际软件博览会(以下简称“软博会”)在天津盛大开幕。KaiwuDB 受邀亮相展会,围绕“塑造软件新生态,赋能发展新变革”主题,重点展示自研分布式多模数据库及各大行业解决方案ÿ…...

RS-485/RS-422收发器电路 DP3085 国产低成本替代MAX3085
DP3085是5V、半双工、15kV ESD 保护的 RS-485/RS-422 收发器电路,电路内部包含一路驱动器和一路接收器。 DP3085具有增强的摆率限制,助于降低输出 EMI 以及不匹配的终端连接引起的反射,实现 500kbps 的无误码数据传输。 DP3085芯片接收器输入…...

R-which函数(带有arr.ind参数)
目录 一、which()函数 二、元素位置 一、which()函数 which()函数是R语言中的一个基础函数,用于返回满足指定条件的元素的位置或索引。 语法:which(x, arr.ind FALSE, useNames TRUE) 参数: - x:一个向量、数组或矩阵&#x…...

单片机通用学习-什么是时钟?
什么是时钟? 时钟是同步单片机系统各个部件工作时序的最小时间单位,时钟通过 CPU 控制,产生其他与时钟保持一定关系的同步控制信号,协调各部件的工作时序,没有时钟系统就崩溃了。 如 CPU 与存储器(RAM&am…...

PCL入门(二):初识点云数据
目录 1. 点云数据2. 对点云数据的简单操作3. 结果 1. 点云数据 在pcl里面,定义了很多点云数据类型,比如PointXYZ、PointXYZI、PointXYZRGBA等等,每一个都可以看做是点云的一个点的数据。而整个点云的数据类型被定义为PointCloud。 以pcl::P…...

LeetCode 面试题 03.01. 三合一
文章目录 一、题目二、C# 题解 一、题目 三合一。描述如何只用一个数组来实现三个栈。 你应该实现push(stackNum, value)、pop(stackNum)、isEmpty(stackNum)、peek(stackNum)方法。stackNum表示栈下标,value表示压入的值。 构造函数会传入一个stackSize参数&#x…...

【WebSocketIndexedDB】node+WebSocketIndexedDB开发简易聊天室
序幕介绍: WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。 讲人话就是说:WebSocket 使得客户端和服务器之间的数据交换变得更加简单,在 WebSocket API 中,浏览器和服务器只需要完成一次握手&#x…...

【01】弄懂共识机制PoW
基于工作量证明机制的共识机制PoW(Proof of Work) 特点就是多劳多特 共识过程 一个区块链系统中,交易历经多个步骤才能得以上链,并且需要经过多个节点的验证。以下是这些步骤的详细叙述: 交易进入交易池(内…...

QT C++ 基于TCP通信的网络聊天室
一、基本原理及流程 1)知识回顾(C语言中的TCP流程) 2)QT中的服务器端/客户端的操作流程 二、代码实现 1)服务器 .ui .pro 在pro文件中添加network库 .h #ifndef WIDGET_H #define WIDGET_H#include <QWidget>…...

SpringMVC入门详细介绍
一. SpringMVC简介 Spring MVC是一个基于Java的实现了MVC设计模式的请求驱动类型的轻量级Web框架,通过把Model,View,Controller分离,将web层进行职责解耦,把复杂的web应用分成逻辑清晰的几部分,简化开发&a…...

R3LIVE源码解析(9) — R3LIVE中r3live_lio.cpp文件
目录 1 r3live_lio.cpp文件简介 2 r3live_lio.cpp源码解析 1 r3live_lio.cpp文件简介 在r3live.cpp文件中创建LIO线程后,R3LIVE中的LIO线程本质上整体流程和FAST-LIO2基本一致。 2 r3live_lio.cpp源码解析 函数最开始会进行一系列的声明和定义,发布的…...

如何高效的解析Json?
Json介绍 Json是一种数据格式,广泛应用在需要数据交互的场景Json由键值对组成每一个键值对的key是字符串类型每一个键值对的value是值类型(boo1值数字值字符串值)Array类型object类型Json灵活性他可以不断嵌套,数组的每个元素还可以是数组或者键值对键值…...

MySQL——分组查询
2023.9.4 MySQL 分组查询的学习笔记如下: #分组查询 /* 分组查询中的筛选条件分为两类:数据源 位置 关键字 分组前筛选 原始表 group by前面 where 分组后筛选 分组后的结果集 group by后面 having */ #查询每…...

thinkphp 使用 easypay 和 easywechat
easypay 是3.x easywechat 是6.x 引入: use Yansongda\Pay\Pay;//easypayuse EasyWeChat\MiniApp\Application as MiniApp;//easywechat use EasyWeChat\Pay\Application as Payapp;//easywechat public function suborder(){$order [out_trade_no > time(…...

无涯教程-JavaScript - DVARP函数
描述 DVARP函数通过使用列表或数据库中符合您指定条件的记录的字段(列)中的数字,基于整个总体计算总体的方差。 语法 DVARP (database, field, criteria)争论 Argument描述Required/Optionaldatabase 组成列表或数据库的单元格范围。 数据库是相关数据的列表,其中相关信息的…...

Databend 开源周报第 108 期
Databend 是一款现代云数仓。专为弹性和高效设计,为您的大规模分析需求保驾护航。自由且开源。即刻体验云服务:https://app.databend.cn 。 Whats On In Databend 探索 Databend 本周新进展,遇到更贴近你心意的 Databend 。 多源数据目录 …...

Android-Intent实现数据传递
在activityA中使用putExtras(bundle)传递数据,在activityB中使用getExtras()获取数据 MainActivity.java及其xml package com.example.intentactivity;import androidx.appcompat.app.AppCompatActivity;import android.content.ComponentName; import android.co…...

系统学习Linux-zabbix监控平台
一、zabbix的基本概述 zabbix是一个监控软件,其可以监控各种网络参数,保证企业服务架构安全运营,同时支持灵活的告警机制,可以使得运维人员快速定位故障、解决问题。zabbix支持分布式功能,支持复杂架构下的监控解决方…...

基于MediaPipe的人体摔倒检测
1 简介 1.1 研究背景及意义 现如今随着经济等各方面飞速发展,社会安全随之也成为必不可少的话题。而校园安全则是社会安全的重中之重,而在我们的校园中,湿滑的地面、楼梯等位置通常会发生摔倒,尽管有“小心脚下”的告示牌…...

WebDAV之π-Disk派盘 + 无忧日记
无忧日记,生活无忧无虑。 给用户专业的手机记录工具,用户可以很轻松地通过软件进行每天发生事情的记录,可以为用户提供优质的工具与帮助,用户还可以通过软件来将地理位置,天气都记录在日记上,用户也可以通过软件来进行图片的导入,创建长图日记, 心情报表:用户写日记…...

Docker 相关操作,及其一键安装Docker脚本
一、模拟CentOS 7.5上安装Docker: 创建一个CentOS 7.5的虚拟机或使用其他方式准备一个CentOS 7.5的环境。 在CentOS 7.5上执行以下命令,以安装Docker的依赖项: sudo yum install -y yum-utils device-mapper-persistent-data lvm2 添加Doc…...

【Microsoft Edge】如何彻底卸载 Edge
目录 一、问题描述 二、卸载 Edge 2.1 卸载正式版 Edge 2.2 卸载非正式版 Edge 2.2.1 卸载通用的 WebView2 2.2.2 卸载 Canary 版 Edge 2.2.3 卸载其他版本 2.3 卸载 Edge Update 2.4 卸载 Edge 的 Appx 额外安装残留 2.5 删除日志文件 2.6 我就是想全把 Edge 都删了…...

2023-09-04力扣每日一题
链接: 449. 序列化和反序列化二叉搜索树 题意: 把一个二叉搜索树变成字符串,还要能变回来 解: 和剑指 Offer 37. 序列化二叉树差不多,那个是二叉树的序列化/反序列化-Hard 直接CV了,懒: ( 如果是二叉…...

jQuery成功之路——jQuery事件和插件概述
一、jQuery的事件 1.1常用事件 jQuery绑定事件,事件名字没有on。 事件名称事件说明blur事件源失去焦点click单击事件源change内容改变keydown接受键盘上的所有键(键盘按下)keypress接受键盘上的部分键(ctrl,alt,shift等无效)(键盘按下)key…...