在SQL中,DQL(Data Query Language,数据查询语言)主要用于检索数据,最常用的DQL命令是 SELECT
。
DQL基本语法
SELECT
字段列表
FROM
表名列表
WHERE
条件列表
GROUP BY
分组字段列表
HAVING
分组后条件列表
ORDER BY
排序字段列表
LIMIT
分页参数
基本查询
查询一个或者多个字段
--使用'*'查询全表。
SELECT * FROM <表名>;
--查询字段,每个字段之间需要用','分隔,最后一个不需要。
SELECT <字段1>,<字段2>,...<字段n> FROM <表名>;
查询时设置别名
--AS设置别名,AS可以省写
SELECT <字段1> [AS 别名1],<字段2> [AS 别名2],...<字段n> [AS 别名n] FROM <表名>;
查询时去除重复记录
--字段列表,可以更具去除多字段下重复的记录
SELECT DISTINCT <字段列表> FROM <表名>;
条件查询--WHERE
语法如下:
SELECT <字段列表>
FROM <表名>
WHERE <条件列表>;
条件运算符列表:
类型 | 符号 | 功能 |
比较运算符 | > | 大于 |
>= | 大于等于或不小于 | |
< | 小于 | |
<= | 小于等于或不大于 | |
= | 等于 | |
<>或!= | 不等于 | |
BETWEEN...AND... | 在AND两侧的范围之间(包括最大、最小值) | |
IN(...) | 在IN后的列表中的任意值 | |
LIKE 占位符('_','%') | 模糊匹配('_' 匹配单个字符,'%'匹配任意个字符) | |
IS NULL | 为空 | |
逻辑运算符 | AND或&& | 并且 (同时成立) |
OR或|| | 或者 (任意一个成立) | |
NOT或! | 非 |
聚合函数
常见函数:
函数 | 功能 |
count | 统计数据 |
max | 最大值 |
min | 最小值 |
avg | 平均值 |
sum | 求和 |
分组查询--GROUP BY
语法如下:
SELECT <字段列表>
FROM <表名>
[WHERE <条件>] --先执行where将满足条件的进行分组
GROUP BY <分组字段名>
[HAVING <分组后过滤条件>]; --分组后的对分组的过滤
--WHERE不能对聚合函数进行判断,但是HAVING可以对聚合函数进行判断
排序查询--ORDER BY
语法如下:
--排序方式:
--ASC 升序
--DESC 降序
SELECT <字段列表>
FROM <表名>
ORDER BY (字段1 排序方式),(字段2 排序方式)...;
--当排序的字段1相同时,会根据字段2的排序方法排序,以此类推。
分页查询--LIMIT
语法如下:
--起始索引是从0开始的,
SELECT <字段列表>
FROM <表名>
LIMIT <起始索引>,<查询数量>;
执行顺序
当执行一个 SELECT
查询时,MySQL和其他数据库管理系统遵循一定的顺序来解析和执行查询。下面是一个典型的 SELECT
查询执行顺序:
-
处理
FROM
子句
首先,MySQL会解析FROM
孀句中的表名或者子查询,并确定需要从哪些表中获取数据。如果有多个表,MySQL会决定表之间的连接方式。 -
处理
JOIN
子句 (关联查询)
如果有JOIN
操作,MySQL会根据指定的连接条件合并多个表的数据。 -
处理
WHERE
子句
接下来,MySQL会应用WHERE
子句中的过滤条件来筛选出符合条件的行。 -
处理
GROUP BY
子句
如果查询中有GROUP BY
子句,MySQL会将结果集按照指定的列进行分组。 -
处理
WITH ROLLUP
或CUBE
(可选)
如果使用了WITH ROLLUP
或CUBE
,MySQL会在分组的基础上生成汇总行。 -
处理
HAVING
子句
在GROUP BY
之后,MySQL会应用HAVING
子句中的过滤条件来进一步筛选分组结果。 -
处理
SELECT
列表
MySQL会从经过以上步骤处理的结果集中选择需要返回的列。 -
处理
DISTINCT
关键字
如果SELECT
子句中包含DISTINCT
,MySQL会去除重复的行。 -
处理
ORDER BY
子句
如果有ORDER BY
子句,MySQL会对结果集进行排序。 -
处理
LIMIT
子句
最后,MySQL会根据LIMIT
子句限制返回的行数。
假设我们有一个数据库,其中包含以下两个表:
employees 表:包含员工的基本信息。
employee_id
(int) - 员工IDfirst_name
(varchar) - 名字last_name
(varchar) - 姓氏department_id
(int) - 部门IDsalary
(decimal) - 薪水hire_date
(date) - 入职日期departments 表:包含部门的信息。
department_id
(int) - 部门IDdepartment_name
(varchar) - 部门名称
现在,假设我们要找出每个部门中薪水高于平均薪水的员工的名字、姓氏以及他们的部门名称。同时,我们还需要列出每个部门的平均薪水。为了实现这一目标,我们可以编写如下的 SQL 查询:
SELECT
e.first_name,
e.last_name,
d.department_name,
e.salary
FROM
employees e
JOIN
departments d ON e.department_id = d.department_id
WHERE
e.hire_date BETWEEN '2020-01-01' AND '2022-12-31'
GROUP BY
e.department_id,
e.first_name,
e.last_name,
e.salary,
d.department_name
HAVING
e.salary > (
SELECT AVG(salary)
FROM employees
WHERE department_id = e.department_id
)
ORDER BY
d.department_name ASC,
e.salary DESC;
接下来,我们将根据先前提到的执行顺序来分析这个查询:
处理
FROM
子句数据库首先识别FROM
子句中的employees
和departments
表。处理
JOIN
子句使用ON
子句中的条件e.department_id = d.department_id
将这两个表连接起来。处理
WHERE
子句应用过滤条件e.hire_date BETWEEN '2020-01-01' AND '2022-12-31'
来筛选出在指定日期范围内的记录。处理
GROUP BY
子句结果集被分组为每个员工和他们所在的部门。处理
WITH ROLLUP
或CUBE
(本查询没有使用这些关键字)由于本查询中没有使用WITH ROLLUP
或CUBE
,此步骤不适用。处理
HAVING
子句对于每个部门,计算该部门的平均薪水,并确保每个员工的薪水都高于该部门的平均值。这里使用了一个子查询来计算每个部门的平均薪水。SELECT AVG(salary) FROM employees WHERE department_id = e.department_id
处理
SELECT
列表从结果集中选取first_name
,last_name
,department_name
, 和salary
列。处理
DISTINCT
关键字本查询中没有使用DISTINCT
关键字,因此此步骤不适用。处理
ORDER BY
子句按照department_name
升序和salary
降序对结果进行排序。处理
LIMIT
子句本查询中没有使用LIMIT
子句。
最终,这个查询将返回每个部门中薪水高于平均薪水的员工的名字、姓氏以及他们的部门名称,同时按部门名称升序和薪水降序排列。