DQL(Data Query Language,数据查询语言)是SQL中最核心的部分,用于从数据库中检索数据。本文以MySQL 8为背景,结合员工表(employees)、部门表(departments)、薪资表(salaries)等业务场景,分入门→进阶→高级三个层级,通过15个实例详细讲解DQL的核心语法和应用。
-- 从employees表中查询所有列的所有记录
SELECT * FROM employees;
讲解:
SELECT *
表示选择表中所有列(*
是通配符)。FROM employees
指定数据来源表为employees
。-- 查询员工姓名(first_name)、邮箱(email)和入职日期(hire_date)
SELECT first_name, email, hire_date
FROM employees;
讲解:
-- 查询薪资大于80000且部门ID为3的员工
SELECT first_name, salary, department_id
FROM employees
WHERE salary > 80000 AND department_id = 3;
讲解:
WHERE
子句用于筛选满足条件的记录,支持逻辑运算符(AND
/OR
/NOT
)和比较运算符(>
/<
/=
/IN
/BETWEEN
等)。AND
表示两个条件需同时满足(薪资>80000 且 部门ID=3)。-- 查询姓名以"John"开头的员工(如John Doe、Johnny)
SELECT first_name, last_name
FROM employees
WHERE first_name LIKE 'John%';
讲解:
LIKE
用于字符串模糊匹配,%
是通配符(表示任意字符序列,包括空)。LIKE '%Doe'
(以"Doe"结尾)、LIKE '%Ann%'
(包含"Ann")。-- 查询所有不同的部门ID(去除重复值)
SELECT DISTINCT department_id
FROM employees;
讲解:
DISTINCT
关键字用于去除结果中的重复行。-- 统计全公司最高工资、最低工资、平均工资、总工资和员工总数
SELECT
MAX(salary) AS max_salary,
MIN(salary) AS min_salary,
AVG(salary) AS avg_salary,
SUM(salary) AS total_salary,
COUNT(*) AS employee_count
FROM employees;
讲解:
MAX()
:最大值(忽略NULL
)。MIN()
:最小值(忽略NULL
)。AVG()
:平均值(自动跳过NULL
)。SUM()
:总和(NULL
视为0)。COUNT(*)
:统计所有行(包括NULL
);COUNT(column)
:统计非NULL
的列值。-- 按部门分组,统计各部门的平均工资和员工数
SELECT
department_id,
AVG(salary) AS dept_avg_salary,
COUNT(*) AS dept_employee_count
FROM employees
GROUP BY department_id;
讲解:
GROUP BY department_id
将数据按department_id
分组,每组内的聚合函数(AVG
/COUNT
)单独计算。-- 查询平均工资超过70000的部门
SELECT
department_id,
AVG(salary) AS dept_avg_salary
FROM employees
GROUP BY department_id
HAVING dept_avg_salary > 70000;
讲解:
HAVING
用于对分组后的结果过滤,与WHERE
的区别:
WHERE
过滤行级数据(分组前)。HAVING
过滤分组后的聚合结果(分组后)。-- 查询员工姓名、部门名称(需关联departments表)
SELECT
e.first_name,
e.last_name,
d.department_name
FROM employees e
INNER JOIN departments d
ON e.department_id = d.department_id;
讲解:
INNER JOIN
(内连接)返回两个表中满足连接条件的记录(e.department_id = d.department_id
)。e
(employees)和d
(departments)简化语句,提高可读性。-- 查询所有员工姓名,即使无对应部门(部门名称显示NULL)
SELECT
e.first_name,
e.last_name,
d.department_name
FROM employees e
LEFT JOIN departments d
ON e.department_id = d.department_id;
讲解:
LEFT JOIN
(左连接)保留左表(employees)的所有记录,右表(departments)无匹配时字段为NULL
。RIGHT JOIN
(右连接,保留右表所有记录)、FULL OUTER JOIN
(全外连接,MySQL 8不直接支持,需用UNION
模拟)。-- 查询工资高于平均工资的员工姓名
SELECT first_name, last_name, salary
FROM employees
WHERE salary > (SELECT AVG(salary) FROM employees);
讲解:
(SELECT AVG(salary) FROM employees)
先计算全公司平均工资,主查询再筛选高于该值的员工。-- 查询员工姓名、部门ID、工资,以及部门内工资排名
SELECT
first_name,
department_id,
salary,
RANK() OVER (PARTITION BY department_id ORDER BY salary DESC) AS dept_salary_rank
FROM employees;
讲解:
RANK()
用于计算分组内的排名(PARTITION BY department_id
按部门分组,ORDER BY salary DESC
按工资降序)。DENSE_RANK()
(密集排名,无间隔)、ROW_NUMBER()
(行号,无重复)。-- 使用CTE临时存储各部门平均工资,再查询高薪部门
WITH dept_avg AS (
SELECT
department_id,
AVG(salary) AS avg_salary
FROM employees
GROUP BY department_id
)
SELECT department_id, avg_salary
FROM dept_avg
WHERE avg_salary > 75000;
讲解:
WITH dept_avg AS (...)
定义一个临时结果集(CTE),后续可直接引用。-- 查询包含"database"或"optimization"关键词的简历(假设employees表有resume_text字段)
SELECT first_name, last_name, resume_text
FROM employees
WHERE MATCH(resume_text) AGAINST('database optimization' IN NATURAL LANGUAGE MODE);
讲解:
MATCH...AGAINST
用于高效搜索文本内容。-- 查询第3页数据(每页10条,跳过前20条)
SELECT * FROM employees
ORDER BY hire_date DESC -- 按入职时间倒序排列(确保分页顺序稳定)
LIMIT 10 OFFSET 20; -- 跳过20条,取10条
讲解:
LIMIT 10
:限制返回10条记录。OFFSET 20
:跳过前20条记录(适用于分页)。OFFSET
过大时性能下降(可通过覆盖索引优化)。层级 | 核心功能 | 典型语句 | 应用场景 |
---|---|---|---|
入门级 | 基础数据检索与过滤 | SELECT 、WHERE 、LIKE 、DISTINCT |
快速查看数据、简单业务报表 |
进阶级 | 聚合统计与多表关联 | GROUP BY 、HAVING 、JOIN |
部门统计、跨表数据整合 |
高级 | 复杂逻辑与性能优化 | 窗口函数、CTE、全文索引、分页 | 数据分析、大数据量查询、文本检索 |
掌握以上15个实例后,可应对90%以上的业务查询需求。实际使用中需注意:
SELECT *
,显式指定列以提高性能。INNER JOIN
,减少冗余数据。OFFSET
过大时,改用WHERE id > last_id
(基于索引的范围查询)优化性能。