一、排序规则:使用ORDER BY
对查询到的数据进行排序操作。
二、ORDER BY
子句在SELECT
语句的结尾。
# 练习:按照salary从高到低的顺序显示员工信息
SELECT employee_id,last_name,salary
FROM employees
ORDER BY salary DESC;
# 练习:按照salary从低到高的顺序显示员工信息
SELECT employee_id,last_name,salary
FROM employees
ORDER BY salary ASC;
SELECT employee_id,last_name,salary
FROM employees
ORDER BY salary; # 如果在ORDER BY 后没有显式指名排序的方式的话,则默认按照升序排列。
#2. 我们可以使用列的别名,进行排序
SELECT employee_id,salary,salary * 12 annual_sal
FROM employees
ORDER BY annual_sal;
#列的别名只能在 ORDER BY 中使用,不能在WHERE中使用。
#如下操作报错!
SELECT employee_id,salary,salary * 12 annual_sal
FROM employees
WHERE annual_sal > 81600;
#3. 强调格式:WHERE 需要声明在FROM后,ORDER BY之前。
# 排序字段可以和查询字段不一样
# 查询语句在查询时不是按照从上到下查询的,而是先找到表(FROM employees),
# 再对表进行过滤(WHERE department_id IN (50,60,70)),然后查询(SELECT employee_id,salary),
# 最后排序(ORDER BY department_id DESC;)
SELECT employee_id,salary
FROM employees
WHERE department_id IN (50,60,70)
ORDER BY department_id DESC;
#4. 二级排序
#练习:显示员工信息,按照department_id的降序排列,针对department_id相同的员工,按照salary的升序排列
SELECT employee_id,salary,department_id
FROM employees
ORDER BY department_id DESC,salary ASC;
一、mysql使用limit
实现数据的分页显示
二、格式:LIMIT [位置偏移量,] 行数
。第一个“位置偏移量”参数指示MySQL从哪一行开始显示,是一个可选参数,如果不指定“位置偏移量”,将会从表中的第一条记录开始(第一条记录的位置偏移量是0,第二条记录的位置偏移量是1,以此类推);第二个参数“行数”指示返回的记录条数。
# 需求1:每页显示20条记录,此时显示第1页
SELECT employee_id,last_name
FROM employees
LIMIT 0,20;
# 需求2:每页显示20条记录,此时显示第2页
SELECT employee_id,last_name
FROM employees
LIMIT 20,20;
# 需求3:每页显示20条记录,此时显示第3页
SELECT employee_id,last_name
FROM employees
LIMIT 40,20;
#需求:每页显示pageSize条记录,此时显示第pageNo页:
#公式:LIMIT (pageNo-1) * pageSize,pageSize;
#2.2 WHERE ... ORDER BY ...LIMIT 声明顺序如下:
#一般ORDER BY ...LIMIT都放在最后,且LIMIT垫底
# LIMIT的格式: 严格来说:LIMIT 位置偏移量,条目数
# 结构"LIMIT 0,条目数" 等价于 "LIMIT 条目数"
SELECT employee_id,last_name,salary
FROM employees
WHERE salary > 6000
ORDER BY salary DESC
#limit 0,10;
LIMIT 10;
#练习:表里有107条数据,我们只想要显示第 32、33 条数据怎么办呢?
SELECT employee_id,last_name
FROM employees
LIMIT 31,2;
#2.3 MySQL8.0新特性:LIMIT ... OFFSET ...
#LIMIT 行数 OFFSET 偏移量
#练习:表里有107条数据,我们只想要显示第 32、33 条数据怎么办呢?
SELECT employee_id,last_name
FROM employees
LIMIT 2 OFFSET 31;
#练习:查询员工表中工资最高的员工信息
SELECT employee_id,last_name,salary
FROM employees
ORDER BY salary DESC
#limit 0,1
LIMIT 1;
#2.4 LIMIT 可以使用在MySQL、PGSQL、MariaDB、SQLite 等数据库中使用,表示分页。
# 不能使用在SQL Server、DB2、Oracle!
一、多表查询,也称为关联查询,指两个或更多个表一起完成查询操作。
二、这些一起查询的表之间是有关系的(一对一、一对多),它们之间一定是有关联字段,这个关联字段可能建立了外键,也可能没有建立外键。比如:员工表和部门表,这两个表依靠“部门编号”进行关联。
三、假如没有多表查询,我们想查询员工名为’Abel’的人在哪个城市工作,需要先去员工表中查询’Abel’的信息,发现他在80部门,然后去部门表中查询80部门的信息,知道了80部门所在位置的代码是2500,然后再去locations表中查询代码是2500的地址:
SELECT *
FROM employees
WHERE last_name = 'Abel';
SELECT *
FROM departments
WHERE department_id = 80;
SELECT *
FROM locations
WHERE location_id = 2500;
四、利用多表查询查询员工的姓名及其部门名称:
SELECT last_name, department_name
FROM employees, departments;
查询出2889条记录,分别查询employees和departments发现每个员工都与每个部门匹配了一遍,我们把这种情况称为笛卡尔积错误。
SELECT *
FROM employees; #107条记录
SELECT 2889 / 107
FROM DUAL;# 27
SELECT *
FROM departments; # 27条记录
五、SQL92中,笛卡尔积也称为交叉连接 ,英文是CROSS JOIN。在 SQL99中也是使用CROSS JOIN表示交叉连接。它的作用就是可以把任意表进行连接,即使这两张表不相关。在MySQL中如下情况会出现笛卡尔积:
SELECT employee_id,department_name
FROM employees CROSS JOIN departments;#查询出2889条记录
六、笛卡尔积的错误会在下面条件下产生:
七、为了避免笛卡尔积, 可以在WHERE
加入有效的连接条件,格式:
SELECT 列名1, 列名2
FROM 表1, 表2
WHERE 表1.列名1 = 表2.列名2; #连接条件
上述查询代码改为:
SELECT employee_id,department_name
FROM employees,departments
#两个表的连接条件
WHERE employees.`department_id` = departments.department_id;
八、如果查询语句中出现了多个表中都存在的字段,则必须指明此字段所在的表,比如我们要查department_id
这个字段,这个字段是employees和departments关联的字段,两个表都有,所以此时我们需要指明到底是查哪个表的department_id
SELECT employee_id,department_name,employees.department_id
FROM employees,departments
WHERE employees.`department_id` = departments.department_id;
九、从sql优化的角度,建议多表查询时,每个字段前都指明其所在的表,所以上述代码建议写为:
SELECT employees.employee_id,departments.department_name,employees.department_id
FROM employees,departments
WHERE employees.`department_id` = departments.department_id;
十、可以给表起别名,在SELECT
和WHERE
中使用表的别名。
SELECT emp.employee_id,dept.department_name,emp.department_id
FROM employees emp,departments dept
WHERE emp.`department_id` = dept.department_id;
如果给表起了别名,一旦在SELECT
或WHERE
中使用表名的话,则必须使用表的别名,而不能再使用表的原名,这是因为代码执行时,先执行FROM employees emp,departments dept
,他知道你给表起了别名就用别名覆盖了原来的表名,以后他只认识别名。如下的操作是错误的:
SELECT emp.employee_id,departments.department_name,emp.department_id
FROM employees emp,departments dept
WHERE emp.`department_id` = departments.department_id;
十一、如果有n个表实现多表的查询,则需要至少n-1个连接条件,且每个连接条件用AND
连接。例如查询员工的employee_id
、last_name
、department_name
、city
SELECT e.employee_id,e.last_name,d.department_name,l.city,e.department_id,l.location_id
FROM employees e,departments d,locations l
WHERE e.`department_id` = d.`department_id`
AND d.`location_id` = l.`location_id`;
十二、多表查询的分类
一、我们前面讲的所有都是等值连接,连接条件中用=
连接两个表的字段:WHERE emp.
department_id = dept.department_id;
,不用=
连接的就是非等值连接
二、现在我们要查询员工的薪资处于哪个级别,代码如下:
SELECT e.last_name,e.salary,j.grade_level
FROM employees e,job_grades j
#where e.`salary` between j.`lowest_sal` and j.`highest_sal`;
WHERE e.`salary` >= j.`lowest_sal` AND e.`salary` <= j.`highest_sal`;
一、自连接:
二、假如我想查询employees表中的员工id,员工姓名及其管理者的id和姓名,那么我需要用取别名的方式将employees表虚拟成两张表以代表不同的意义,然后两个表再进行内连接,外连接等查询:
SELECT emp.employee_id,emp.last_name,mgr.employee_id,mgr.last_name
FROM employees emp ,employees mgr
WHERE emp.`manager_id` = mgr.`employee_id`;
一、内连接:合并具有同一列的两个以上的表的行,结果集中不包含一个表与另一个表不匹配的行。也就是说我们只把满足查询条件的数据查出来了,其他的数据没有要
SELECT employee_id,department_name
FROM employees e,departments d
WHERE e.`department_id` = d.department_id; #只有106条记录
二、外连接:两个表在连接过程中除了返回满足连接条件的行以外还返回左(或右)表中不满足条件的行 ,这种连接称为左(或右) 外连接。没有匹配的行时,结果表中相应的列为空(NULL)。也就是说外连接就是把不满足条件的数据也查出来了,如果把左表中不满足条件的查出来了就叫左外连接,如果把右表中不满足条件的查出来了,就叫右外连接,如果左右表中不满足体哦阿健的都被查出来了,就叫满连接
一、在SQL92中采用(+)
代表从表所在的位置。即左或右外连接中,(+)
表示哪个是从表。
二、在SQL92中,只有左外连接和右外连接,没有满(或全)外连接。
三、MySQL不支持SQL92语法中外连接的写法!Oracle支持
#不支持:
SELECT employee_id,department_name
FROM employees e,departments d
WHERE e.`department_id` = d.department_id(+);
在数据少的那个表后面写
(+)
一、SQL99语法中使用JOIN ...ON
的方式实现多表的查询。这种方式也能解决外连接的问题。MySQL是支持此种方式的。
SELECT table1.column, table2.column,table3.column
FROM table1
JOIN table2 ON table1 和 table2 的连接条件
JOIN table3 ON table2 和 table3 的连接条件
说明:
JOIN
、INNER JOIN
、CROSS JOIN
一样,都用来内连接ON
子句指定额外的连接条件。#SQL99语法实现内连接:
SELECT last_name,department_name
FROM employees e INNER JOIN departments d
ON e.`department_id` = d.`department_id`;
SELECT last_name,department_name,city
FROM employees e JOIN departments d
ON e.`department_id` = d.`department_id`
JOIN locations l
ON d.`location_id` = l.`location_id`;
二、SQL99语法实现外连接:
#练习:查询所有的员工的last_name,department_name信息
# 左外连接:
SELECT last_name,department_name
FROM employees e LEFT JOIN departments d
ON e.`department_id` = d.`department_id`;
#右外连接:
SELECT last_name,department_name
FROM employees e RIGHT OUTER JOIN departments d
ON e.`department_id` = d.`department_id`;
LEFT JOIN
等同于LEFT OUTER JOIN
RIGHT JOIN
等同于RIGHT OUTER JOIN
MySQL不支持满外连接FULL JOIN,但是可以用LEFT JOIN UNION RIGHT JOIN
代替
合并查询结果利用UNION
关键字,可以给出多条SELECT
语句,并将它们的结果组合成单个结果集。合并时,两个表对应的列数和数据类型必须相同,并且相互对应。各个SELECT
语句之间使用UNION
或UNION ALL
关键字分隔。
SELECT column,... FROM table1
UNION [ALL]
SELECT column,... FROM table2
说明:
UNION
操作符返回两个查询的结果集的并集,去除重复记录。UNION ALL
操作符返回两个查询的结果集的并集。对于两个结果集的重复部分,不去重。UNION ALL
语句时所需要的资源比UNION
语句少,因为UNION ALL
会对合并结果去重。如果明确知道合并数据后的结果数据不存在重复数据,或者不需要去除重复的数据,则尽量使用UNION ALL
语句,以提高数据查询的效率。# 中图:内连接
SELECT employee_id,department_name
FROM employees e JOIN departments d
ON e.`department_id` = d.`department_id`;
# 左上图:左外连接
SELECT employee_id,department_name
FROM employees e LEFT JOIN departments d
ON e.`department_id` = d.`department_id`;
# 右上图:右外连接
SELECT employee_id,department_name
FROM employees e RIGHT JOIN departments d
ON e.`department_id` = d.`department_id`;
# 左中图:
SELECT employee_id,department_name
FROM employees e LEFT JOIN departments d
ON e.`department_id` = d.`department_id`
WHERE d.`department_id` IS NULL;
# 右中图:
SELECT employee_id,department_name
FROM employees e RIGHT JOIN departments d
ON e.`department_id` = d.`department_id`
WHERE e.`department_id` IS NULL;
# 左下图:满外连接
# 方式1:左上图 UNION ALL 右中图
SELECT employee_id,department_name
FROM employees e LEFT JOIN departments d
ON e.`department_id` = d.`department_id`
UNION ALL
SELECT employee_id,department_name
FROM employees e RIGHT JOIN departments d
ON e.`department_id` = d.`department_id`
WHERE e.`department_id` IS NULL;
# 方式2:左中图 UNION ALL 右上图
SELECT employee_id,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,department_name
FROM employees e RIGHT JOIN departments d
ON e.`department_id` = d.`department_id`;
# 右下图:左中图 UNION ALL 右中图
SELECT employee_id,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,department_name
FROM employees e RIGHT JOIN departments d
ON e.`department_id` = d.`department_id`
WHERE e.`department_id` IS NULL;
NATURAL JOIN
:我们可以把自然连接理解为SQL92中的等值连接。它会帮你自动查询两张连接表中所有相同的字段 ,然后进行等值连接 :
SELECT employee_id,last_name,department_name
FROM employees e NATURAL JOIN departments d;
等同于SQL92标准中:
SELECT employee_id,last_name,department_name
FROM employees e JOIN departments d
ON e.`department_id` = d.`department_id`
AND e.`manager_id` = d.`manager_id`;
一、可以使用USING
指定数据表里的同名字段进行等值连接。但是只能配合JOIN
一起使用。
SELECT employee_id,last_name,department_name
FROM employees e JOIN departments d
USING (department_id);
等同于SQL92标准中:
SELECT employee_id,last_name,department_name
FROM employees e JOIN departments d
ON e.department_id = d.department_id;
二、USING
连接与自然连接NATURAL JOIN
不同的是,USING
指定了具体的相同的字段名称,你需要在USING
的括号()
中填入要指定的同名字段。同时使用JOIN...USING
可以简化JOIN ON
的等值连接。
三、表连接的约束条件可以有三种方式:WHERE
,ON
,USING
WHERE
:适用于所有关联查询ON
:只能和JOIN
一起使用,只能写关联条件。虽然关联条件可以并到WHERE
中和其他条件一起写,但分开写可读性更好。USING
:只能和JOIN
一起使用,而且要求两个关联字段在关联表中名称一致,而且只能表示关联字段值相等