目录
1、基本的SELECT语句
1.0 SELECT
1.1 SELECT ... FROM
1.2 列的别名
1.3 去除重复行
1.4 空值参与运算
1.5 着重号
2. 显示表结构
2.0使用DESCRIBE 或 DESC 命令,表示表结构。
3.条件筛选
3.0 语法:
4.SELECT和运算符的运用
4.0.算术运算符
4.1. 比较运算符
4.2非符号类型的运算符:
4.3. 逻辑运算符
4.4 . 位运算符
5.SELECT与排序与分页
5.0.排序规则
5.1.单列排序
5.2 多列排序
5.3.分页
6.SELECT多表查询
6.0易出现笛卡尔积错误分析
6.2多表查询分类讲解
分类1:等值连接 vs 非等值连接
6.3分类2:自连接 vs 非自连接
6.4分类3:内连接 vs 外连接
7.子查询
7.1 子查询的基本使用
7.2 子查询的分类
7.3EXISTS 与 NOT EXISTS关键字
SELECT ; #没有任何子句
例如:
SELECT 标识选择哪些列
FROM 标识从哪个表中选择
例如1:选择全部列:
例如2:选择特定的列:
规则:
- 紧跟列名,也可以在列名和别名之间加入关键字AS(AS 可以省略),别名使用双引号,以便在别名中 包含空格或特 殊的字符并区分大小写。
- 重命名一个列,建议别名简短,见名知意,便于计算。
例如:
默认情况下,查询会返回全部行,包括重复行。
例如:SELECT department_id
FROM employees;
在SELECT语句中使用关键字DISTINCT去除重复行
SELECT DISTINCT department_id
FROM employees;
所有运算符或列值遇到null值,运算的结果都为null.在 MySQL 里面, 空值不等于空字符串。一个空字符串的长度是 0,而一个空值的长 度是空。而且,在 MySQL 里面,空值是占用空间的。
例如:
我们需要保证表中的字段、表名等没有和保留字、数据库系统或常用方法冲突。如果真的相同,请在 SQL语句中使用一对``(着重号)引起来。
例如:
ORDER BY:对查询结果进行排序 在 MySQL SELECT 语句中
Field:表示字段名称。
Type:表示字段类型
Null:表示该列是否可以存储NULL值。
Key:表示该列是否已编制索引(主键)。PRI表示该列是表主键的一部分;UNI表示该列是UNIQUE索引的一 部分;MUL表示在列中某个给定值允许出现多次。
Default:表示该列是否有默认值,如果有,那么值是多少。
Extra:表示可以获取的与给定列有关的附加信息。
SELECT 字段1,字段2
FROM 表名
WHERE 过滤条件
注意:使用WHERE 子句,将不满足条件的行过滤掉
WHERE子句紧随 FROM子句
例如:查询年龄大于20的
在Java中,+的左右两边如果有字符串,那么表示字符串的拼接。但是在MySQL中+只表示数 值相加。如果遇到非数值类型,先尝试转成数值,如果转失败,就按0计算。
一个数乘以整数1和除以整数1后仍得原数但 一个数乘以浮点数1和除以浮点数1后变成浮点数,数值与原数相等; 一个数除以整数后,不管是否能除尽,结果都为一个浮点数; 一个数除以另一个数,除不尽时,结果为一个浮点数,并保留到小数点后4位; 乘法和除法的优先级相同,进行先乘后除操作与先除后乘操作,得出的结果相同。 在数学运算中,0不能用作除数,在MySQL中,一个数除以0为NULL。
比较运算符用来对表达式左边的操作数和右边的操作数进行比较,比较的结果为真则返回1,比较的结果 为假则返回0,其他情况则返回NULL。 比较运算符经常被用来作为SELECT查询语句的条件来使用,返回符合条件的结果记录。
1.等号运算符
等号运算符(=)判断等号两边的值、字符串或表达式是否相等,如果相等则返回1,不相等则返回 0。
在使用等号运算符时,遵循如下规则:
如果等号两边的值、字符串或表达式都为字符串,则MySQL会按照字符串进行比较,其比较的 是每个字符串中字符的ANSI编码是否相等。
如果等号两边的值都是整数,则MySQL会按照整数来比较两个值的大小。
如果等号两边的值一个是整数,另一个是字符串,则MySQL会将字符串转化为数字进行比较。
如果等号两边的值、字符串或表达式中有一个为NULL,则比较结果为NULL。
2. <=>:安全等于相当于等于但他可以对空值操作。使用安全等于运算符时,两边的操作数的值都为NULL时,返回的结果为1而不是NULL,其他 返回结果与等于运算符相同。
3.不等于运算符 不等于运算符(<>和!=)用于判断两边的数字、字符串或者表达式的值是否不相等, 如果不相等则返回1,相等则返回0。不等于运算符不能判断NULL值。如果两边的值有任意一个为NULL, 或两边都为NULL,则结果为NULL。
1. 空运算符
2 . 非空运算符 (IS NOT NULL)判断一个值是否不为NULL,如果不为NULL则返回1,否则返 回0。
3. 最小值运算符 语法格式为:LEAST(值1,值2,...,值n)。其中,“值n”表示参数列表中有n个值。在有 两个或多个参数的情况下,返回最小值。
结论:当参数是整数或者浮点数时,LEAST将返回其中最小的值;当参数为字符串时,返回字 母表中顺序最靠前的字符;当比较值列表中有NULL时,不能判断大小,返回值为NULL。
若LEAST(able,apple):比较规则a与a比较,b与p比较,l与p比较...在b与p比较是b
4.BETWEEN AND运算符
使用的格式通常为SELECT D
FROM TABLE
WHERE C BETWEEN A AND B,
此时,当C大于或等于A,并且C小于或等于B时,结果为1,否则结果为0。
5. IN运算符 用于判断给定的值是否是IN列表中的一个值,如果是则返回1,否则返回0。如果给 定的值为NULL,或者IN列表中存在NULL,则结果为NULL。
6 . NOT IN运算符 NOT IN运算符用于判断给定的值是否不是IN列表中的一个值,如果不是IN列表中的一 个值,则返回1,否则返回0。
7. . LIKE运算符 LIKE运算符主要用来匹配字符串,通常用于模糊匹配,如果满足条件则返回1,否则返回 0。如果给定的值或者匹配条件为NULL,则返回结果为NULL。
LIKE运算符通常使用如下通配符:
“%”:匹配0个或多个字符。 “_”:只能匹配一个字符。
例如:查询名字中有S且后边可以有0个或多个任意字符
Sname
查询名字含有o且o前只有一个字符的
aopp
ESCAPE:回避特殊符号的:使用转义符。例如:将[%]转为[$%]、[]转为[$],然后再加上[ESCAPE‘$’]即可。如果使用\表示转义,要省略ESCAPE。如果不是\,则要加上ESCAPE。
8. REGEXP运算符
在fruits表中,查询f_name字段以字母‘b’开头的记录,SQL语句如下:
mysql> SELECT * FROM fruits WHERE f_name REGEXP '^b';
逻辑运算符主要用来判断表达式的真假,在MySQL中,逻辑运算符的返回结果为1、0或者NULL。
1.逻辑非运算符 (NOT或!)运算符表示当给定的值为0时返回1;当给定的值为非0值时返回0; 当给定的值为NULL时,返回NULL。
2.逻辑与运算符 (AND或&&)运算符是当给定的所有值均为非0值,并且都不为NULL时,返回 1;当给定的一个值或者多个值为0时则返回0;否则返回NULL。
注意: OR可以和AND一起使用,但是在使用时要注意两者的优先级,由于AND的优先级高于OR,因此先 对AND两边的操作数进行操作,再与OR中的操作数结合。
4.逻辑异或运算符 (XOR)运算符是当给定的值中任意一个值为NULL时,则返回NULL;如果 两个非NULL的值都是0或者都不等于0时,则返回0;如果一个值为0,另一个值不为0时,则返回1。
位运算符是在二进制数上进行计算的运算符。位运算符会先将操作数变成二进制数,然后进行位运算, 最后将计算结果从二进制变回十进制数。
1.按位与运算符(&)运算符将给定值对应的二进制数逐位进行逻辑与运算。当给定值对应的二 进制位的数值都为1时,则该位返回1,否则返回0。
2. 按位或运算符 (|)运算符将给定的值对应的二进制数逐位进行逻辑或运算。当给定值对应的 二进制位的数值有一个或两个为1时,则该位返回1,否则返回0。
3.按位异或运算符(^)运算符将给定的值对应的二进制数逐位进行逻辑异或运算。当给定值对应的 二进制位的数值有两个为1或两个0时,则该位返回0,否则返回1。
4. 按位取反运算符 (~)运算符将给定的值的二进制数逐位进行取反操作,即将1变为0,将0变 为1。
5. 按位右移运算符(>>)运算符将给定的值的二进制数的所有位右移指定的位数。右移指定的 位数后,右边低位的数值被移出并丢弃,左边高位空出的位置用0补齐。
6. 按位左移运算符 (<<)运算符将给定的值的二进制数的所有位左移指定的位数。左移指定的 位数后,左边高位的数值被移出并丢弃,右边低位空出的位置用0补齐。
使用 ORDER BY 子句排序
ASC(ascend): 升序
DESC(descend):降序
ORDER BY 子句在SELECT语句的结尾。
年龄进行升序排序
学号进行升序排序
在对多列进行排序的时候,首先排序的第一列必须有相同的列值,才会对第二列进行排序。如果第 一列数据中所有值都是唯一的,将不再对第二列进行排序。
应用场景:查询返回的记录太多了,查看起来很不方便,能够实现分页查询
表里有 4 条数据,我们只想要显示第 2、3 条数据可以使用分页
分页原理:所谓分页显示,就是将数据库中的结果集,一段一段显示出来需要的条件。
MySQL中使用 LIMIT 实现分页
格式:LIMIT [位置偏移量,] 行数
分页显式公式:(当前页数-1)*每页条数,每页条数
SELECT *
FROM table
LIMIT(PageNo - 1)*PageSize,PageSize;
注意:LIMIT 子句必须放在整个SELECT语句的最后!
多表查询,也称为关联查询,指两个或更多个表一起完成查询操作。
案例:查询员工的姓名及其部门名称
SELECT last_name, department_name
FROM employees, departments;
(EMPLOYEES表有107调数据 DEPARTMENTS有27条数据 107*27=2889,
相当于EMPLOYEES中每个last-name和 DEPARTMENTS中的department-name中每个都 匹配了一遍)我们把上述多表查询中出现的问题称为:笛卡尔积的错误。
为了避免笛卡尔积, 可以在 WHERE 加入有效的连接条件。
正确写法:
SELECT last_name, department_name
FROM employees, departments
WHERE employees.department_id = departments.department_id;
分类1:等值连接 vs 非等值连接
平时写的带等号的就是等值连接
SELECT departments.location_id
FROM employees, departments
WHERE employees.department_id = departments.department_id;
多个表中有相同列时,必须在列名之前加上表名前缀。
SELECT employees.last_name, departments.department_name,employees.department_id FROM employees, departments
WHERE employees.department_id = departments.department_id;
也可使用别名可以简化查询。 列名前使用表名前缀可以提高查询效率
SELECT e.employee_id, e.last_name, e.department_id, d.department_id, d.location_id FROM employees e , departments d
WHERE e.department_id = d.department_id;
连接 n个表,至少需要n-1个连接条件。
非等值连接 :一般带有>=或BETWEEN...AND语句
非自连接:不同的表相连接
自连接:自己链接自己
题目:查询employees表,返回“Xxx works for Xxx
SELECT CONCAT(worker.last_name ,' works for ' , manager.last_name)
FROM employees worker, employees manager
WHERE worker.manager_id = manager.employee_id ;
内连接:只显示表中符合条件的数据也就是只有两个表相匹配的行才能在结果集中出现
语法:
SELECT 字段列表
FROM A表( INNER) JOIN B表
ON 关联条件
(WHERE 等其他子句;)
练习:查询employee_id, last_name, department_id,department_id, location_id
SELECT e.employee_id, e.last_name, e.department_id, d.department_id, d.location_id FROM employees e JOIN departments d
ON (e.department_id = d.department_id);
外连接(OUTER JOIN)的实现:显示表中所以数据,两个表不匹配的也会显示,多表查询出现所有、全部词语就是外连接。外连接不仅包含符合连接条件的行,还包含左表(左连接时)、右表(右连接时)或两个边接表(全外连接)中的所有数据行。
左外连接(LEFT OUTER JOIN):左连接就是将JOIN前面的表中所有记录都展示出来。
语法:
SELECT 字段列表
FROM A表 LEFT JOIN B表
ON 关联条件
WHERE 等其他子句;
查询所有员工的last_name,department_id,department_name
SELECT e.last_name, e.department_id, d.department_name
FROM employees e LEFT OUTER JOIN departments d
ON (e.department_id = d.department_id) ;
右外连接:(RIGHT OUTER JOIN):右连接就是将JOIN后面的表中所有记录都展示出来。
SELECT 字段列表
FROM A表 RIGHT JOIN B表
ON 关联条件
WHERE 等其他子句;
显示所有部门名称和对应的部门号和姓名
SELECT e.last_name, e.department_id, d.department_name
FROM employees e RIGHT OUTER JOIN departments d
ON (e.department_id = d.department_id) ;
满外连接(FULL OUTER JOIN)
满外连接的结果 = 左右表匹配的数据 + 左表没有匹配到的数据 + 右表没有匹配到的数据。 SQL99是支持满外连接的。使用FULL JOIN 或 FULL OUTER JOIN来实现。 需要注意的是,MySQL不支持FULL JOIN,但是可以用 LEFT JOIN UNION RIGHT join代替。
UNION的使用:合并查询结果
SELECT column,...
FROM table1
UNION [ALL]
SELECT column,...
FROM table2
UNION 操作符返回两个查询的结果集的并集,去除重复记录。
UNION ALL操作符返回两个查询的结果集的并集。对于两个结果集的重复部分,不去重。
举例:查询部门编号>90或邮箱包含a的员工信息
SELECT *
FROM employees
WHERE email LIKE '%a%'
UNION
SELECT *
FROM employees
WHERE department_id>90;
#中图:内连接 A∩B
SELECT employee_id,last_name,department_name
FROM employees e JOIN departments d
ON e.`department_id` = d.`department_id`;
#左上图:左外连接
SELECT employee_id,last_name,department_name
FROM employees e LEFT JOIN departments d
ON e.`department_id` = d.`department_id`;
#右上图:右外连接
SELECT employee_id,last_name,department_name
FROM employees e RIGHT JOIN departments d
ON e.`department_id` = d.`department_id`;
#左中图:A - A∩B
SELECT employee_id,last_name,department_name
FROM employees e LEFT JOIN departments d
ON e.`department_id` = d.`department_id`
WHERE d.`department_id` IS NULL
#右中图:B-A∩B
SELECT employee_id,last_name,department_name
FROM employees e RIGHT JOIN departments d
ON e.`department_id` = d.`department_id` WHERE e.`department_id` IS NULL
左下图:左上图+右中图
SELECT employee_id,last_name,department_name
FROM employees e LEFT JOIN departments d
ON e.`department_id` = d.`department_id`
WHERE d.`department_id` IS NULL
UNION ALL #没有去重操作,效率高
SELECT employee_id,last_name,department_name
FROM employees e RIGHT JOIN departments d
ON e.`department_id` = d.`department_id`;
#右下图 #左中图 + 右中图
SELECT employee_id,last_name,department_name
FROM employees e LEFT JOIN departments d
ON e.`department_id` = d.`department_id`
WHERE d.`department_id` IS NULL
UNION ALL
SELECT employee_id,last_name,department_name
FROM employees e RIGHT JOIN departments d
ON e.`department_id` = d.`department_id`
WHERE e.`department_id` IS NULL
子查询指一个查询语句嵌套在另一个查询语句内部的查询
注意:1.子查询(内查询)在主查询之前一次执行完成。
2.子查询的结果被主查询(外查询)使用 。
3.子查询要包含在括号内
4.将子查询放在比较条件的右侧, 单行操作符对应单行子查询,多行操作符对应多行子查询
我们按内查询的结果返回一条还是多条记录,将子查询分为 单行子查询 、 多行子查询 。
单行子查询
单行比较操作符
CASE中的子查询
CASE语句遍历条件并在满足第一个条件时返回一个值(如IF-THEN-ELSE语句)。因此,一旦条件为真,它将停止读取并返回结果。如果没有条件为 true,则返回 ELSE 子句中的值。
如果没有其他部分,并且没有条件为 true,则返回 NULL。
子查询中的空值问题
非法使用子查询:多行子查询使用单行比较符号。
多行子查询:内查询返回多行 使用多行比较操作符
体会 ANY 和 ALL 的区别
例如: 返回其它job_id中比job_id为‘IT_PROG’部门任一工资低的员工的员工号、姓名、job_id 以及salary
例如 :返回其它job_id中比job_id为‘IT_PROG’部门所有工资都低的员工的员工号、姓名、job_id以及
查询平均工资最低的部门id
#方式1: SELECT department_id
FROM employees
GROUP BY department_id
HAVING AVG(salary) = (
SELECT MIN(avg_sal)
FROM ( SELECT AVG(salary) avg_sal
FROM employees
GROUP BY department_id )
dept_avg_sal #表名
)
#方式2:
SELECT department_id
FROM employees
GROUP BY department_id
HAVING AVG(salary) <= ALL (
SELECT AVG(salary) avg_sal
FROM employees
GROUP BY department_id )
相关子查询
如果子查询的执行依赖于外部查询,通常情况下都是因为子查询中的表用到了外部的表,并进行了条件 关联,因此每执行一次外部查询,子查询都要重新计算一次,这样的子查询就称之为 关联子查询 。
关联子查询通常也会和 EXISTS操作符一起来使用,用来检查在子查询中是否存在满足条件的行。 如果在子查询中不存在满足条件的行: 条件返回 FALSE 继续在子查询中查找
如果在子查询中存在满足条件的行: 不在子查询中继续查找 条件返回 TRUE
NOT EXISTS关键字表示如果不存在某种条件,则返回TRUE,否则返回FALSE。