1.基础查询
语法: select 查询列表 from 表名;
其中 :
- 表中的字段、常量值、表达式、函数
- 查询字段:
select 字段(多个字段中间逗号隔开) from 表名; - 查询常量值:
select 100;
select ‘john’;
注意:字符型和日期型的常量必须用单引号引起来,数值型不需要。 - 查询表达式:
select 100%98; - 查询函数:
select version(); - 查询表达式:
select 100/1234;(支持加减乘除取模)
- 查询的结果是一个虚拟的表格
起别名(当别名刚好与关键字相同时,需要加双引号)
方式一:使用as
//例如:
select last_name as 姓,first_name as 名 from employees;
方式二:使用空格
//例如:
select last_name 姓,first_name 名 from employees;
去重
//例如:
select distinct department_id from employees;
“+”号的作用
MySQL中“+”号仅仅只有一个功能:运算符。例如两个操作数用“+”号连接,如果两个操作数都为数值型则做加法运算;如果其中一个为字符型,会试图将字符型转换成数值型,如果转换成功则做加法运算,如果转换失败,则将字符型数值转换为0,继续做加法运算;如果其中一方为null,则结果为null。
拼接多个字符用concat(str1,str2,…,strn)函数
同样的,当其中一个字符stri为null时,最后结果也将为null。
2.条件查询
语法: select 查询列表 from 表名 where 筛选条件;
分类:
- 按条件表达式筛选
- 简单条件运算符:>、<、=、!=或<>、>=、<=
#例如:查询部门编号不等于90号的员工名和部门编号
SELECT
`last_name`,
`department_id`
FROM
`employees`
WHERE
`department_id`!=90;
- 按逻辑表达式筛选
- 逻辑运算符:&& || ! 或 and or not
#按逻辑表达式筛选
SELECT
`last_name`,
`salary`,
`commission_pct`
FROM
`employees`
WHERE
# `salary`>10000&&`salary`<20000;
`salary` BETWEEN 10000 AND 20000;
#例如:查询部门编号不是在90到110之间,或者工资高于15000的员工信息
SELECT
*
FROM
`employees`
WHERE
(!(`department_id`>= 90 `department_id`<=110))||`salary`>15000
- 模糊查询
like、between and、in、is null、is not null
#模糊查询中可以使用通配符
# %:代表任意个字符
# _:代表任意单个字符
#like
#例如:查询员工名中第二个字符为_的员工名
SELECT
last_name
FROM
employees
WHERE
last_name LIKE '_$_%' ESCAPE '$';//指定转义字符'$'
#in
/*
判断某字段的值是否属于in列表中的某一项,in列表中的值类型需要保持一致
或者兼容。
*/
#例如:查询员工的工种编号是IT_PROT、AD_VP、AD_PRES中的一个员工名和工种编号
SELECT
`last_name`,
`job_id`
FROM
`employees`
WHERE
`job_id` IN ('IT_PROT','AD_VP','AD_PRES');
/*
=或者<>不能用于判断null值
is null或is not null可以判断null值
*/
ifnull函数
判断某字段或表达式是否为null,如果为null,返回指定的值,否则返回原本的值。
#例如:判断commission_pct值是否为null,如果为null返回0;如果不为null返回原本值。
SELECT
last_name,salary,IFNULL(commission_pct,0)
FROM
employees
WHERE
`commission_pct` IS NULL;
isnull函数
功能:判断某字段或表达式是否为null,如果是返回1,否则返回0。
SELECT last_name,salary FROM employees WHERE salary<18000 AND ISNULL(commission_pct);
3.排序查询
语法: select 查询列表 from 表名 [where 筛选条件] order by 排序列表 [asc|desc]
特点:
- asc代表升序;desc代表降序,如果不写,默认按升序排。
- order by子句中可以支持单个字段、多个字段、表达式、函数、别名。
- order by子句一般放在语句的最后面,limit子句除外。
SELECT * FROM employees ORDER BY salary ASC;
SELECT * FROM employees ORDER BY salary DESC;
//查询员工的姓名、部门号和年薪,按年薪降序,姓名升序
SELECT last_name,department_id,salary*12*(1+IFNULL(commission_pct,0)) 年薪
FROM employees
ORDER BY 年薪 DESC,last_name ASC;
4.常见函数
使用: select 函数名(实参列表) [from 表];
分类:
- 单行函数,如concat、length、ifnull等。
- 分组函数,做统计使用,又称为统计函数、聚合函数、组函数。
Ⅰ.单行函数
①字符函数
注意:SQL中索引从1开始。
-
length:获取参数值的字节个数。
SELECT LENGTH('john');
-
concat:拼接字符串。
SELECT CONCAT('john','_','bobo');//john_bobo
-
upper、lower
# 将姓变为大写,名字变为小写,然后拼接字符串 SELECT CONCAT(UPPER(last_name),'_',LOWER(first_name)) FROM employees;
-
substr或者substring
#截取从指定索引处开始后面的字符 SELECT SUBSTR('梁山伯爱上了朱丽叶',7); #截取从指定索引处,指定长度的字符 SELECT SUBSTR('梁山伯爱上了朱丽叶',1,3); #例:姓名中首字符大写,其他字符小写,然后用“_”拼接 SELECT CONCAT(UPPER(SUBSTR(last_name,1,1)),'_',LOWER(SUBSTR(last_name,2))) FROM employees;
-
instr:返回子串在主串中出现的第一次索引,如果找不到返回0
SELECT INSTR('梁山伯爱上了朱丽叶','朱丽叶');//7
-
trim:去除两端空白(并可以去除指定字符)
SELECT TRIM(' 哈哈 ');//哈哈 SELECT TRIM('a' FROM 'aaaaa哈aa哈aaaaaa');//哈aa哈
-
lpad、rpad:用指定字符实现左填充指定长度、用指定字符实现右填充指定长度
SELECT LPAD('haha',10,'*');//******haha SELECT RPAD('haha',10,'*');//haha******
-
rerplace:替换
SELECT REPLACE('我的我的我的','我','你');//你的你的你的
②数学函数
-
round:四舍五入
SELECT ROUND('1.62');#2 SELECT ROUND('1.632',2);#1.63,保留两位小数
-
ceil、floor:向上取整;向下取整
SELECT CEIL('1.055');#2 SELECT FLOOR('1.999');#1
-
truncate:截断
SELECT TRUNCATE('1.666666',2)#1.66,保留小数点后两位
-
mod:取模运算
SELECT MOD(10,3);#1
-
rand:获取随机数,返回[0,1)之间的小数
③日期函数
-
now():返回当前系统日期+时间
SELECT NOW();
-
curdate():返回当前日期,不包含时间
SELECT CURDATE();
-
curtime():返回当时时间,不包含日期
SELECT CURTIME();
-
获取当前时间的指定年、月、日、时、分、秒部分,也可以自己指定时间
SELECT YEAR(NOW()); SELECT YEAR('2020-07-23');#2020 SELECT YEAR('2020.07.23');#2020 SELECT MONTHNAME(NOW());#英文月份 SELECT MONTH(NOW()); SELECT DAYNAME(NOW());#英文,周几 SELECT DAY(NOW());#号数 SELECT HOUR(NOW()); SELECT MINUTE(NOW()); SELECT SECOND(NOW());
-
str_to_date:将字符通过指定的格式解析成日期
SELECT STR_TO_DATE('4 3 2020','%c %d %Y');#按照后面这种格式去解析,可得到日期 SELECT * FROM employees WHERE hiredate = STR_TO_DATE('4 3 1992','%c %d %Y'); #表中日期为第一个参数的字符,按照第二个参数进行解析,得到日期,进行筛选
-
date_format:将日期按照指定格式格式化成字符
#查询有奖金的员工名和入职日期(xx月/xx日/xx年) SELECT last_name,DATE_FORMAT(hiredate,'%m月/%d日/%Y年') FROM employees WHERE commission_pct IS NOT NULL;
④其他函数
- select version(); 查看当前版本号
- select database(); 查看当前数据库
- select user(); 查看当前用户
- select md5(str):返回MD5的加密形式
⑤流程控制函数
-
if(expr1,expr2,expr3):如果满足expr1条件则执行expr2,否则执行expr3
SELECT IF(10>5,'大','小');#大
-
case的使用一:实现switch case语句的效果
语法:
当case与select搭配的时候,then后只能是要显示的值且不能加分号;
当case不与select搭配的时候,then可以是语句,要加分号。case 要判断的字段或者表达式
when 常量1 then 要显示的值1或执行的语句1;
when 常量2 then 要显示的值2或执行的语句2;
…
else 要显示的值n或语句n;
end/* 例:查询员工的工资,要求: 部门号=30,显示的工资为1.1倍 部门号=40,显示的工资为1.2倍 部门号=50,显示的工资为1.3倍 其他部门,显示的工资为原工资 */ SELECT salary AS 原工资, CASE department_id WHEN 30 THEN salary*1.1 WHEN 40 THEN salary*1.2 WHEN 50 THEN salary*1.3 ELSE salary END AS 新工资 FROM employees;
-
case的使用二:实现多重if的效果
语法
当case与select搭配的时候,then后只能是要显示的值且不能加分号;
当case不与select搭配的时候,then可以是语句,要加分号。case
when 常量1 then 要显示的值1或执行的语句1
when 常量2 then 要显示的值2或执行的语句2
…
else 要显示的值n或语句n;
end/* 例:查询员工的工资情况 如果工资>20000,显示A级别 如果工资>15000,显示B级别 如果工资>10000,显示C级别 否则,显示D级别 */ SELECT salary, CASE WHEN salary>20000 THEN 'A' WHEN salary>15000 THEN 'B' WHEN salary>10000 THEN 'C' ELSE 'D' END AS 工资级别 FROM employees;
Ⅱ.分组函数
功能: 用作统计使用,又称为聚合函数、统计函数或组函数。多个输入,一个输出。
分类: sum 求和;avg 平均值;max 最大 值;min 最小值;count 计算个数。
SELECT AVG(DISTINCT salary),SUM(salary),MAX(salary),MIN(salary),COUNT(salary)
FROM employees;
说明:
- sum、avg一般用于处理数值型;max、min、count可以处理任何类型。
- 以上分组函数均会忽略null值。
- 可以和distinct搭配实现去重的运算。
- count函数
#两种方式都可以用来统计表中行数 SELECT COUNT(*) FROM employees; SELECT COUNT(1) FROM employees;
- 和分组函数一同查询的字段要求是group by后的字段。
5.分组查询
语法:
select 分组函数,列(要求出现在group by的后面)
from 表
[where 筛选条件]
group by 分组的列表
[order by 子句]
注意: 查询列表(select后的字段)必须特殊,要求是分组函数和group by后出现的字段。
特点:
a). 分组查询中的筛选条件分为两类:
数据源 | 位置 | 关键字 | |
---|---|---|---|
分组前筛选 | 原始表 | group by子句的前面 | where |
分组后筛选 | 分组后的结果集 | group by子句的后面 | having |
- 分组函数做条件必须放在having子句中
- 能用分组前筛选的,就优先考虑使用分组前筛选
b). group by子句支持单个、多个字段、表达式、函数(较少)分组。在多个字段分组时,字段之间用逗号隔开,没有顺序要求)。
c). 可以添加排序(排序放在整个分组查询的最后)。
例子:
#查询每个工种的最高工资
SELECT MAX(salary),job_id
FROM employees
GROUP BY job_id;
#查询邮箱中包含a字符的,每个部门的平均工资
SELECT AVG(salary),department_id
FROM employees
WHERE email LIKE '%a%'
GROUP BY department_id
#查询有奖金的每个领导手下员工的最高工资
SELECT MAX(salary),manager_id
FROM employees
WHERE commission_pct IS NOT NULL
GROUP BY manager_id
#添加分组后的筛选条件
#查询哪个部门的员工个数>2
SELECT COUNT(1),department_id
FROM employees
GROUP BY department_id
HAVING COUNT(1)>2;
#查询每个工种有奖金的员工的最高工资>12000的工种编号和最高工资
SELECT job_id,MAX(salary)
FROM employees
WHERE commission_pct IS NOT NULL
GROUP BY job_id
HAVING MAX(salary)>12000
#查询领导编号>102的每个领导手下的最低工资>5000的领导编号是哪个,以及其最低工资
SELECT manager_id,MIN(salary)
FROM employees
WHERE manager_id>102
GROUP BY manager_id
HAVING MIN(salary)>5000;
#按表达式或函数分组
#例子:按员工姓名的长度分组,查询每一组的员工个数,筛选员工个数>5的有哪些
SELECT COUNT(1),LENGTH(last_name)
FROM employees
GROUP BY LENGTH(last_name)
HAVING COUNT(1)>5
#按多个字段分组
#例子:查询每个部门每个工种的员工的平均工资
SELECT AVG(salary),department_id,job_id
FROM employees
GROUP BY department_id,job_id;
6.连接查询
含义: 又称多表查询,当查询的字段来自于多个表时,就会用到连接查询。
分类:
按年代分类:
sql92标准:仅仅支持内连接
sql99标准:支持内连接+外连接(左外和右外)+交叉连接
按功能分类:
内连接:等值连接、非等值连接、自连接
外连接:左外连接、右外连接、全外连接
交叉连接
Ⅰ.sql92标准
①等值连接
多表等值连接的结果为多表的交集部分;
n表连接,至少需要n-1个连接条件;
多表的顺序没有要求;
一般需要为表起别名;
可以搭配前面介绍的所有子句使用,例如排序、分组、筛选等。
语法:
select 查询列表
from 表1 别名,表2 别名
where 表1.key=表2.key
[and 筛选条件]
[group by 分组字段]
[having 分组后的筛选]
[order by 排序字段]
-
查询不同表之间的数据
#查询员工名和对应的部门名 SELECT last_name,department_name FROM employees,departments WHERE employees.`department_id`=departments.`department_id`;
-
给表起别名后如果用到表名就要用别名
SELECT e.last_name,e.job_id,j.job_title FROM employees AS e,jobs AS j WHERE j.`job_id`=e.`job_id`;
-
from后表的顺序可以调换
-
可以加筛选,where子句后加and关键字进行筛选
#查询有奖金的员工名、部门名 SELECT employees.`last_name`,departments.`department_name` FROM employees,departments WHERE employees.`department_id`=departments.`department_id` AND employees.`commission_pct` IS NOT NULL; #查询城市名中第二个字符为o的部门名和城市名 SELECT d.`department_name`,l.`city` FROM departments d,locations l WHERE d.`location_id`=l.`location_id` AND l.`city` LIKE '_o%';
-
可以加分组
#查询每个城市的部门个数 SELECT COUNT(department_id),city FROM departments d,locations l WHERE d.`location_id`=l.`location_id` GROUP BY l.`city`;
-
可以加排序
#查询每个工种的工种名和员工的个数,并且按员工个数降序 SELECT job_title,COUNT(1) FROM employees e,jobs j WHERE e.`job_id`=j.`job_id` GROUP BY j.job_title ORDER BY COUNT(1) DESC;
-
可以实现三表查询
#查询员工名、部门名和所在的城市,并且要求城市名以s开头,按部门名降序排列 SELECT last_name,departments.department_name,city FROM employees,departments,locations WHERE employees.`department_id`=departments.`department_id` AND departments.`location_id`=locations.`location_id` AND city LIKE 's%' ORDER BY departments.`department_name` DESC;
②非等值连接
非等值连接是基于等值连接知识的,同样可以加各种排序、分组等操作。
#查询员工的工资和工资级别
SELECT salary,grade_level
FROM employees e,job_grades g
WHERE e.`salary` BETWEEN g.`lowest_sal` AND g.`highest_sal`
AND g.`grade_level`='A';
③自连接
自连接就跟等值连接一样,不过等值连接连接的是不同表,而自连接连接的是自己;也就是在相同的一张表上按不同的字段名来建立连接。
#查询员工名和上级领导的名字
SELECT e.`employee_id`,e.last_name,m.`last_name`,m.`employee_id`
FROM employees e, employees m
WHERE e.`employee_id`=m.`manager_id`
Ⅱ.sql99标准
语法:
select 查询列表
from 表1 别名
[连接类型] join 表2 别名 on 连接条件
[连接条件] join 表3 别名 on 连接条件
…
[连接条件] join 表n 别名 on 连接条件
[where 筛选条件]
[group by 分组]
[having 筛选条件]
[order by 排序列表]
其中,[连接类型]的值为:inner(内连接)、left[outer] (左外连接)、right[outer] (右外连接)、full[outer] (全外连接)、cross(交叉连接)。
①内连接
-
等值连接
特点:可以添加排序、分组、筛选等
inner可以省略
筛选条件放在where后面,连接条件放在on后面
inner join连接和sql92标准中等值连接效果一样,都是查询多表的交集#查询员工名、部门名 SELECT last_name,department_name FROM employees e INNER JOIN departments d ON e.`department_id`=d.`department_id`; #查询名字中包含e的员工名和工种名(添加筛选) SELECT last_name,job_title FROM employees e INNER JOIN jobs j ON e.`job_id`=j.`job_id` WHERE last_name LIKE '%e%' #查询部门个数>3的城市名和部门个数(分组+筛选) SELECT city,COUNT(*) FROM locations l INNER JOIN departments d ON l.location_id=d.location_id GROUP BY city HAVING COUNT(*)>3; #查询哪个部门的部门员工个数>3对的部门名和员工个数,并按个数降序(排序) SELECT department_name,COUNT(*) FROM employees e INNER JOIN departments d ON e.`department_id`=d.`department_id` GROUP BY department_name HAVING COUNT(*)>3 ORDER BY COUNT(*) DESC; #查询员工名、部门名、工种名、并按部门名降序(三表连接) SELECT last_name,department_name,job_title FROM employees e INNER JOIN departments d ON e.`department_id`=d.`department_id` INNER JOIN jobs j ON e.`job_id`=e.`job_id` ORDER BY department_name DESC;
-
非等值连接
#查询员工的工资级别 SELECT salary,grade_level FROM employees e INNER JOIN job_grades j ON e.`salary` BETWEEN j.`lowest_sal` AND j.`highest_sal`; #查询每个工资级别的个数>20的个数,并且按工资级别降序 SELECT COUNT(*),j.`grade_level` FROM employees e INNER JOIN job_grades j ON e.`salary` BETWEEN j.`lowest_sal` AND j.`highest_sal` GROUP BY j.`grade_level` HAVING COUNT(*)>20 ORDER BY j.`grade_level` DESC;
-
自连接
#查询姓名中包含k的员工的名字和其上级的名字 SELECT e.last_name,m.`last_name` FROM employees e INNER JOIN employees m ON e.`manager_id`=m.`employee_id` WHERE e.`last_name` LIKE '%k%';
②外连接
应用场景: 用于查询一个表中没有(一般做主表),另一个表中有的记录
特点:
- 外连接的查询结果为主表中的所有记录
如果从表中有和它匹配的,则显示匹配的值
如果从表中没有和它匹配的,则显示null
外连接查询结果=内连接查询结果+主表中有而从表中没有的记录 - 左外连接,left join左边的是主表;右外连接,right join右边的是主表
- 左外和右外交换两个表的顺序,可以实现同样的效果
- 全外连接=内连接的结果+表1中有但表2中没有的记录+表2中有但表1中没有的记录
-
左外
#查询哪个部门没有员工 SELECT d.*,e.employee_id FROM departments d LEFT OUTER JOIN employees e ON d.department_id=e.department_id WHERE e.employee_id IS NULL;
-
右外
#查询哪个部门没有员工 SELECT d.*,e.employee_id FROM employees e RIGHT OUTER JOIN departments d ON d.department_id=e.department_id WHERE e.employee_id IS NULL;
-
全外连接目前MySQL不支持
③交叉连接
假如表1中有11条记录,表2中有4条记录,那么交叉连接后就有44条记录(笛卡尔乘积)
SELECT * FROM beauty;#12行
SELECT * FROM boys;#4行
SELECT b.*,bo.*
FROM beauty b
CROSS JOIN boys bo;#48行
7.子查询
含义: 出现在其他语句中的select语句,称为子查询或内查询;外部的查询语句称为主查询或外查询。
分类:
按结果集的行列数不同:
- 标量子查询(结果集只有一行一列)
- 列子查询(结果集只有一列多行)
- 行子查询(结果集有一行多列或多行多列)
- 表子查询(结果集一般为多行多列)
按子查询出现的位置:
- select 后面:仅仅支持标量子查询
- from 后面:支持表子查询
- where或having后面:标量子查询(单行)、列子查询(多行)、行子查询
- exists后面(相关子查询):表子查询、标量子查询、列子查询、行子查询
Ⅰ where或having后面
- 标量子查询
- 列子查询
- 行子查询
特点:
- 子查询放在小括号内
- 子查询一般放在条件的右侧
- 标量子查询,一般搭配单行操作符使用。单行操作符:>、<、>=、<=、=、<>
列子查询,一般搭配多行操作符使用。多行操作符:in、any/some、all - 子查询的执行优先于主查询执行,主查询的条件用到了子查询的结果
①标量子查询
单行操作符>、<、>=、<=、=、<>后的子查询结果需要是单行的。
#谁的工资比Abel高?
SELECT *
FROM employees
WHERE salary>(
SELECT salary
FROM employees
WHERE last_name='Abel'
)
#返回job_id与141号员工相同,salary比143号员工多的员工 姓名,job_id和工资
SELECT last_name,job_id,salary
FROM employees
WHERE job_id=(
SELECT job_id
FROM employees
WHERE employee_id=141
) AND salary>(
SELECT salary
FROM employees
WHERE employee_id=143
);
#返回公司工资最少的员工的last_name,job_id和salary
SELECT job_id,salary,last_name
FROM employees
WHERE salary=(
SELECT MIN(salary)
FROM employees
)
#查询最低工资大于50号部门最低工资的部门id和其最低工资
SELECT MIN(salary),department_id
FROM employees
GROUP BY department_id
HAVING MIN(salary)>(
SELECT MIN(salary)
FROM employees
WHERE department_id=50
)
②列子查询(多行子查询)
列子查询是一列多行。多行操作符有:
操作符 | 含义 |
---|---|
IN/NOT IN | 等于列表中的任意一个 |
ANY|SOME | 和子查询返回的某一个值比较 |
ALL | 和子查询返回的所有值比较 |
#返回location_id是1400或1700的部门中的所有员工姓名
SELECT last_name
FROM employees
WHERE department_id IN(
SELECT DISTINCT department_id
FROM departments
WHERE location_id IN (1400,1700)
)
③行子查询(结果集一行多列或多行多列)
#查询员工编号最小,并且工资最高的员工信息
#以前的方法
SELECT *
FROM employees
WHERE employee_id=(
SELECT MIN(employee_id)
FROM employees
WHERE salary=(
SELECT MAX(salary)
FROM employees
)
);#或
SELECT *
FROM employees
WHERE employee_id=(
SELECT MIN(employee_id)
FROM employees
) AND salary=(
SELECT MAX(salary)
FROM employees
);
#行子查询方法
SELECT *
FROM employees
WHERE (employee_id,salary)=(
SELECT MIN(employee_id),MAX(salary)
FROM employees
);
Ⅱ select后面
仅仅支持标量子查询
#查询每个部门的员工个数
SELECT *,(
SELECT COUNT(*)
FROM employees
WHERE employees.`department_id`=departments.`department_id`
)
FROM departments;
Ⅲ from后面
将子查询结果充当一张表,要求必须起别名
#查询每个部门的平均工资的工资等级
SELECT grade_level,e.*
FROM (
SELECT AVG(salary) AS a,department_id
FROM employees
GROUP BY department_id
) AS e
JOIN job_grades j
ON e.a BETWEEN j.`lowest_sal` AND j.`highest_sal`
Ⅳ exists后面(相关子查询)
语法:
exists(完整的查询语句)
结果为0或1,如果查询语句的查询结果不为空返回1,为空返回0.
(exists可以in代替)
#查询有员工的部门名
SELECT department_name
FROM departments d
WHERE EXISTS(
SELECT *
FROM employees e
WHERE d.department_id=e.`department_id`
)
8.分页查询
应用场景: 当要显示的数据,一页显示不全,需要分页提交sql请求
语法:
select 查询列表
from 表
[join type join 表2
on 连接条件
where 筛选条件
group by 分组字段
having 分组后的筛选
order by 排序的字段]
limit offset,size
- offset代表要显示条目的起始索引(起始索引从0开始)
- size代表要显示的条目个数
特点:
- limit语句放在查询语句的最后
- 要显示的页数page,每页的条目数size,有关系offset=(page-1)*size,size=size。
#查询有奖金的员工信息,并且工资较高的前10名显示出来
SELECT *
FROM employees
WHERE commission_pct IS NOT NULL
ORDER BY salary DESC
LIMIT 0,10
9.联合查询
联合、合并:将多条查询语句的结果合并成一个结果。
语法:
查询语句1
union
查询语句2
union
…
应用场景: 要查询的结果来自于多个表,且多个表之间没有直接的连接关系,但查询的信息一致时。
特点:
- 要求多条查询语句的查询列数一致
- 要求多条查询语句的查询每一列的类型和顺序最好一致
- union关键字默认去重,如果使用union all可以包含重复项