SQL(Structured Query Language)是用于管理关系型数据库的标准语言。
而MySQL 作为最流行的开源关系型数据库之一,其 SQL 实现遵循标准,但也拥有一些自身的特性和函数。本文将详细讲解 MySQL 中的各种查询方法,助你高效地获取所需数据。
一、 基础查询 (SELECT)
SELECT 语句用于从数据库中选取数据,这是最核心的查询命令。
-
查询所有列 (
SELECT *)
使用星号 (*) 可以返回指定表中的所有列。-- 假设我们有一张名为 `employees` 的表 SELECT * FROM employees;注意:在生产环境中谨慎使用
SELECT *,最好明确指定需要的列,以减少不必要的网络传输和资源消耗。 -
查询特定列 (
SELECT column)
你可以明确指定一个或多个列名,用逗号分隔。SELECT first_name, last_name, salary FROM employees; -
列别名 (
AS)
使用AS关键字可以为列指定一个别名,使结果集更易读。AS可以省略。SELECT first_name AS '名', last_name AS '姓', salary * 12 AS '年薪' FROM employees;
二、 结果排序 (ORDER BY)
ORDER BY 子句用于对结果集进行排序,默认是升序 (ASC),降序使用 DESC。
-- 按薪水从高到低排序
SELECT first_name, salary
FROM employees
ORDER BY salary DESC;
-- 按部门升序排,同部门内按薪水降序排
SELECT first_name, department_id, salary
FROM employees
ORDER BY department_id ASC, salary DESC;
三、 条件过滤 (WHERE)
WHERE 子句用于提取满足指定条件的记录。
-
基本运算符 (
=,<>/!=,>,<,>=,<=)SELECT * FROM employees WHERE salary > 10000; SELECT * FROM employees WHERE department_id = 10; SELECT * FROM employees WHERE first_name != 'John'; -
逻辑运算符 (
AND,OR,NOT)
用于组合多个条件。-- 薪资在 8000 到 12000 之间的员工 SELECT * FROM employees WHERE salary >= 8000 AND salary <= 12000; -- 部门是10或20的员工 SELECT * FROM employees WHERE department_id = 10 OR department_id = 20; -- 除了10部门以外的所有员工 SELECT * FROM employees WHERE NOT department_id = 10; -- 等价于 SELECT * FROM employees WHERE department_id <> 10; -
模糊查询 (
LIKE)
%代表任意字符(包括0个),_代表一个任意字符。-- 查找名字以 'J' 开头的员工 SELECT * FROM employees WHERE first_name LIKE 'J%'; -- 查找名字中包含 'an' 的员工 SELECT * FROM employees WHERE first_name LIKE '%an%'; -- 查找名字第二个字母是 'o' 的员工 SELECT * FROM employees WHERE first_name LIKE '_o%'; -
空值判断 (
IS NULL/IS NOT NULL)
判断字段是否为NULL,不能直接用= NULL。-- 查询佣金为空的员工 SELECT * FROM employees WHERE commission_pct IS NULL; -- 查询佣金不为空的员工 SELECT * FROM employees WHERE commission_pct IS NOT NULL;
四、 去重与截断
-
去重 (
DISTINCT)
返回唯一不同的值。-- 查看公司里有哪些不同的部门ID SELECT DISTINCT department_id FROM employees; -- 多列组合去重 SELECT DISTINCT department_id, job_id FROM employees; -
截断与分页 (
LIMIT,OFFSET)
MySQL 使用LIMIT来限制返回的记录数,常用于分页。OFFSET指定开始返回记录前的偏移量。-- 查看薪水最高的5名员工 SELECT * FROM employees ORDER BY salary DESC LIMIT 5; -- 实现分页(每页10条,查看第3页的数据) -- 公式: LIMIT page_size OFFSET (page_number - 1) * page_size SELECT * FROM employees LIMIT 10 OFFSET 20; -- 跳过前20条,取接下来的10条 -- MySQL 也支持简写: LIMIT 20, 10
五、 分支表达式 (CASE WHEN)
CASE 表达式用于实现条件逻辑,类似于编程语言中的 if-else。
SELECT
first_name,
salary,
CASE
WHEN salary > 15000 THEN '高薪'
WHEN salary BETWEEN 8000 AND 15000 THEN '中等'
ELSE '普通'
END AS '薪资等级'
FROM employees;
六、 分组聚合 (GROUP BY & HAVING)
-
分组 (
GROUP BY)
将相同值的行分组到一起,并与聚合函数(如SUM,COUNT,AVG)一起使用。-- 单级分组:计算每个部门的平均薪资 SELECT department_id, AVG(salary) AS avg_salary FROM employees GROUP BY department_id; -- 多级分组:计算每个部门内每个职位的员工数量和总薪资 SELECT department_id, job_id, COUNT(*) AS employee_count, SUM(salary) AS total_salary FROM employees GROUP BY department_id, job_id; -
过滤分组 (
HAVING)
WHERE在分组前过滤行,而HAVING在分组后过滤分组。-- 筛选出员工数量超过5人的部门 SELECT department_id, COUNT(*) AS emp_count FROM employees GROUP BY department_id HAVING COUNT(*) > 5; -- 筛选出平均薪资超过10000的部门 SELECT department_id, AVG(salary) AS avg_salary FROM employees GROUP BY department_id HAVING AVG(salary) > 10000;
七、 常用函数
-
时间函数
-- 获取当前日期和时间 SELECT NOW(); -- 获取当前日期 SELECT CURDATE(); -- 日期格式化 SELECT DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i:%s'); -- 输出: 2023-10-27 15:30:45 -- 日期加减 SELECT DATE_ADD(NOW(), INTERVAL 1 DAY); -- 加一天 SELECT DATE_SUB(NOW(), INTERVAL 1 HOUR); -- 减一小时 -- 计算日期差 SELECT DATEDIFF('2023-12-31', '2023-10-27'); -- 返回相差的天数 -
字符串函数
-- 连接字符串 SELECT CONCAT(first_name, ' ', last_name) AS full_name FROM employees; -- 转大写/小写 SELECT UPPER('hello'), LOWER('WORLD'); -- 截取子串 SELECT SUBSTRING('MySQL', 3, 3); -- 输出: SQL (从第3位开始,截取3位) -- 长度 SELECT LENGTH('Hello'); -- 输出: 5 -
聚合函数
COUNT(),SUM(),AVG(),MAX(),MIN()。SELECT COUNT(*) AS total_employees, -- 总行数 SUM(salary) AS total_salary_payout, -- 总和 AVG(salary) AS average_salary, -- 平均值 MAX(salary) AS highest_salary, -- 最大值 MIN(salary) AS lowest_salary -- 最小值 FROM employees;
八、 高级查询:开窗函数 (Window Functions)
开窗函数对一组行进行计算,但不像 GROUP BY,每个行仍然单独返回。MySQL 8.0+ 开始支持。
-
SUM OVER():计算分区内的总和-- 计算每个员工及其所在部门的总薪资 SELECT first_name, department_id, salary, SUM(salary) OVER(PARTITION BY department_id) AS dept_total_salary FROM employees; -
SUM OVER(ORDER BY):计算累计和-- 按薪水排序,计算累计薪水 SELECT first_name, salary, SUM(salary) OVER(ORDER BY salary) AS running_total FROM employees; -
ROW_NUMBER(),RANK(),DENSE_RANK():排名-- 为每个部门内的员工按薪水排名 SELECT first_name, department_id, salary, ROW_NUMBER() OVER(PARTITION BY department_id ORDER BY salary DESC) AS 'row_number_rank', RANK() OVER(PARTITION BY department_id ORDER BY salary DESC) AS 'rank', DENSE_RANK() OVER(PARTITION BY department_id ORDER BY salary DESC) AS 'dense_rank' FROM employees; -
LAG()/LEAD():访问前面/后面行的数据-- 查看当前行和前一个员工的薪水差值 SELECT first_name, salary, LAG(salary) OVER(ORDER BY salary) AS prev_salary, salary - LAG(salary) OVER(ORDER BY salary) AS diff_from_prev FROM employees;
九、 关联查询 (JOIN)
用于从多个表中查询相关数据。
-
内连接 (
INNER JOIN或JOIN)
返回两个表中连接字段相匹配的行。-- 假设还有一张 `departments` 表,有 department_id 和 department_name 字段 SELECT e.first_name, e.last_name, d.department_name FROM employees e -- 使用别名简化 INNER JOIN departments d ON e.department_id = d.department_id; -
左连接 (
LEFT JOIN)
返回左表 (employees) 的所有行,即使右表没有匹配的行。右表无匹配则为NULL。-- 查询所有员工及其部门信息(包括没有部门的员工) SELECT e.first_name, d.department_name FROM employees e LEFT JOIN departments d ON e.department_id = d.department_id; -
右连接 (
RIGHT JOIN)
与左连接相反,返回右表的所有行,即使左表没有匹配的行。 -
全外连接 (
FULL OUTER JOIN)
返回左右表中所有的行。MySQL 不直接支持FULL OUTER JOIN,通常用LEFT JOIN和RIGHT JOIN的UNION来模拟。
十、 子查询 (Subqueries)
一个查询嵌套在另一个查询中。
-- 1. 在 WHERE 中作为条件:查询薪水高于平均薪水的员工
SELECT * FROM employees
WHERE salary > (SELECT AVG(salary) FROM employees);
-- 2. 在 FROM 中作为派生表:查询每个部门的平均薪水,并筛选出高于公司平均薪水的部门
SELECT dept_avg.*
FROM (
SELECT department_id, AVG(salary) AS avg_sal
FROM employees
GROUP BY department_id
) AS dept_avg
WHERE dept_avg.avg_sal > (SELECT AVG(salary) FROM employees);
十一、 组合查询 (UNION & UNION ALL)
用于合并两个或多个 SELECT 语句的结果集。
UNION:删除重复的记录。UNION ALL:保留所有记录,包括重复的。性能更好,因为不需要去重。
-- 假设有两张表:current_employees 和 former_employees,结构相同
-- 获取所有当前和过往员工的唯一姓名列表
SELECT first_name FROM current_employees
UNION
SELECT first_name FROM former_employees;
-- 获取所有姓名列表(包括重复的)
SELECT first_name FROM current_employees
UNION ALL
SELECT first_name FROM former_employees;
希望这篇详细的 MySQL 查询方法汇总能成为你学习和工作中的有力参考。实践是掌握 SQL 的最佳途径,打开你的 MySQL 客户端,尝试运行这些示例并修改它们来适应你的数据吧!
1992

被折叠的 条评论
为什么被折叠?



