引言
各位数据库探索者们好!今天我们要深入MySQL最核心的部分——数据查询语言(DQL) 🚀。查询数据就像寻宝一样,掌握了正确的"藏宝图"(SQL语句),就能从海量数据中精准找到你需要的信息!无论是简单的用户查询,还是复杂的报表分析,都离不开SELECT语句的强大功能。本教程将带你系统学习从基础查询到高级分析的各种技巧,让你从SQL新手成长为查询高手!💪
一、SELECT语句基础:数据查询的起点
1.1 最简单的查询:检索所有数据
就像打开一本书的第一页一样简单 📖:
-- 查询表中所有列的所有行
SELECT * FROM employees;
-- 查询特定列
SELECT first_name, last_name, salary FROM employees;
注意事项:
SELECT *
会返回所有列,性能较差,生产环境慎用- 明确指定需要的列是好的编程习惯
- 结果集的列顺序与SELECT中的顺序一致
1.2 列别名:让结果更易读
给列起个"绰号",让输出更友好 😊:
-- 使用AS关键字(推荐)
SELECT
employee_id AS "员工ID",
first_name AS "名字",
salary*12 AS "年薪"
FROM employees;
-- 简写形式(省略AS)
SELECT
employee_id "员工ID",
first_name "名字",
salary*12 "年薪"
FROM employees;
1.3 使用表达式:计算字段
SQL也能做数学运算 ➕➖✖️➗:
-- 基本计算
SELECT
product_name,
price,
quantity,
price*quantity AS total_value
FROM order_items;
-- 使用函数
SELECT
CONCAT(first_name, ' ', last_name) AS full_name,
YEAR(hire_date) AS hire_year
FROM employees;
二、WHERE条件查询:精准筛选数据
2.1 基本条件查询
WHERE就像筛子,过滤出你需要的数据 🕵️:
-- 比较运算符
SELECT * FROM products WHERE price > 100;
SELECT * FROM employees WHERE department_id = 10;
-- 日期比较
SELECT * FROM orders WHERE order_date >= '2023-01-01';
常用比较运算符:
=
等于<>
或!=
不等于>
大于<
小于>=
大于等于<=
小于等于
2.2 逻辑运算符:组合多个条件
AND、OR、NOT就像逻辑开关 🔌:
-- AND(同时满足)
SELECT * FROM employees
WHERE salary > 5000 AND department_id = 20;
-- OR(满足其一)
SELECT * FROM products
WHERE category_id = 5 OR category_id = 8;
-- NOT(取反)
SELECT * FROM customers
WHERE NOT country = 'USA';
2.3 特殊条件查询
BETWEEN:范围查询:
-- 闭区间包含边界值
SELECT * FROM products
WHERE price BETWEEN 50 AND 100;
-- 等价于
SELECT * FROM products
WHERE price >= 50 AND price <= 100;
IN:多值匹配:
SELECT * FROM employees
WHERE department_id IN (10, 20, 30);
-- 等价于
SELECT * FROM employees
WHERE department_id = 10
OR department_id = 20
OR department_id = 30;
LIKE:模糊查询:
-- %匹配任意多个字符
SELECT * FROM customers
WHERE name LIKE '张%'; -- 张开头
-- _匹配单个字符
SELECT * FROM products
WHERE product_code LIKE 'A_B%'; -- A开头,第三个字母B
NULL值判断:
-- 查询没有部门的员工
SELECT * FROM employees
WHERE department_id IS NULL;
-- 查询有部门的员工
SELECT * FROM employees
WHERE department_id IS NOT NULL;
三、ORDER BY排序:有序展示结果
3.1 单列排序
让结果按某种顺序排列 🔼🔽:
-- 升序(默认)
SELECT * FROM products
ORDER BY price;
-- 降序
SELECT * FROM employees
ORDER BY hire_date DESC;
3.2 多列排序
先按第一列排,相同再按第二列… 🗂️:
SELECT * FROM employees
ORDER BY department_id ASC, salary DESC;
3.3 按表达式或别名排序
-- 按表达式排序
SELECT
first_name,
last_name,
salary*12 AS annual_salary
FROM employees
ORDER BY salary*12 DESC;
-- 按别名排序(MySQL支持)
SELECT
first_name,
last_name,
salary*12 AS annual_salary
FROM employees
ORDER BY annual_salary DESC;
四、GROUP BY分组与聚合函数
4.1 聚合函数:数据统计
像Excel的数据透视表一样汇总 📊:
-- 常用聚合函数
SELECT
COUNT(*) AS total_employees,
AVG(salary) AS avg_salary,
MAX(salary) AS max_salary,
MIN(salary) AS min_salary,
SUM(salary) AS total_salary
FROM employees;
4.2 GROUP BY:分组统计
把数据分成若干小组分别统计 👥:
-- 按部门统计薪资
SELECT
department_id,
COUNT(*) AS emp_count,
AVG(salary) AS avg_salary
FROM employees
GROUP BY department_id;
注意事项:
- SELECT中的非聚合列必须出现在GROUP BY中
- 可以按多列分组
- NULL值会被分为一组
4.3 常用聚合函数详解
函数 | 描述 | 示例 |
---|---|---|
COUNT() | 计数 | COUNT(*), COUNT(列名) |
SUM() | 求和 | SUM(salary) |
AVG() | 平均值 | AVG(score) |
MAX() | 最大值 | MAX(price) |
MIN() | 最小值 | MIN(age) |
GROUP_CONCAT() | 将分组值连接成字符串 | GROUP_CONCAT(name SEPARATOR ‘,’) |
GROUP_CONCAT示例:
-- 列出每个部门的员工姓名
SELECT
department_id,
GROUP_CONCAT(first_name ORDER BY hire_date SEPARATOR ', ') AS employees
FROM employees
GROUP BY department_id;
五、HAVING子句:过滤分组结果
5.1 HAVING vs WHERE
HAVING就像WHERE,但是针对分组后的结果 🚦:
-- 查询平均薪资大于6000的部门
SELECT
department_id,
AVG(salary) AS avg_salary
FROM employees
GROUP BY department_id
HAVING AVG(salary) > 6000;
区别:
- WHERE在分组前过滤行
- HAVING在分组后过滤组
- WHERE不能使用聚合函数
- HAVING可以使用聚合函数
5.2 HAVING复杂条件
-- 多条件HAVING
SELECT
department_id,
COUNT(*) AS emp_count,
AVG(salary) AS avg_salary
FROM employees
GROUP BY department_id
HAVING COUNT(*) > 5 AND AVG(salary) > 6000;
-- 结合ORDER BY
SELECT
department_id,
AVG(salary) AS avg_salary
FROM employees
GROUP BY department_id
HAVING AVG(salary) > 5000
ORDER BY avg_salary DESC;
六、DISTINCT去重:消除重复值
6.1 基本去重
去掉结果中的重复行 ✨:
-- 查询所有不重复的部门ID
SELECT DISTINCT department_id
FROM employees;
-- 多列去重
SELECT DISTINCT department_id, job_id
FROM employees;
6.2 DISTINCT与聚合函数
-- 计算不重复的部门数量
SELECT COUNT(DISTINCT department_id)
FROM employees;
-- 计算每个部门不重复的职位数
SELECT
department_id,
COUNT(DISTINCT job_id) AS unique_jobs
FROM employees
GROUP BY department_id;
6.3 DISTINCT性能考虑
- DISTINCT会进行排序去重,大数据量可能影响性能
- 有时可以用GROUP BY替代DISTINCT
- 在索引列上使用DISTINCT效率更高
七、LIMIT分页查询:控制结果集
7.1 基本分页查询
像书本分页一样展示数据 📄:
-- 查询前5条记录
SELECT * FROM products LIMIT 5;
-- 从第6条开始查询5条记录(LIMIT 偏移量, 数量)
SELECT * FROM products LIMIT 5, 5;
7.2 分页参数计算
-- 假设每页显示10条,查询第3页
SELECT * FROM orders
ORDER BY order_date DESC
LIMIT 20, 10; -- (3-1)*10=20
7.3 高性能分页技巧
问题:偏移量大时性能差(如LIMIT 10000,10)
解决方案1:使用索引覆盖
-- 先通过索引找到主键
SELECT id FROM products
ORDER BY create_time
LIMIT 10000, 10;
-- 再获取详细数据
SELECT * FROM products
WHERE id IN (上述查询结果);
解决方案2:记住上一页最后一条的ID
-- 假设上一页最后一条的id是12345
SELECT * FROM products
WHERE id > 12345
ORDER BY id
LIMIT 10;
八、综合案例:电商数据查询实战
8.1 多表联合查询
-- 查询订单详情(用户信息+订单信息)
SELECT
o.order_id,
o.order_date,
c.customer_name,
c.phone,
o.total_amount
FROM orders o
JOIN customers c ON o.customer_id = c.customer_id
WHERE o.order_date BETWEEN '2023-01-01' AND '2023-01-31'
ORDER BY o.total_amount DESC
LIMIT 10;
8.2 复杂统计分析
-- 按月统计各品类销售额
SELECT
DATE_FORMAT(o.order_date, '%Y-%m') AS month,
p.category,
SUM(oi.quantity * oi.unit_price) AS total_sales,
COUNT(DISTINCT o.order_id) AS order_count
FROM orders o
JOIN order_items oi ON o.order_id = oi.order_id
JOIN products p ON oi.product_id = p.product_id
WHERE o.order_date >= '2022-01-01'
GROUP BY month, p.category
HAVING total_sales > 10000
ORDER BY month, total_sales DESC;
8.3 子查询应用
-- 查询高于部门平均薪资的员工
SELECT
e.employee_id,
e.first_name,
e.salary,
e.department_id,
d.avg_salary
FROM employees e
JOIN (
SELECT
department_id,
AVG(salary) AS avg_salary
FROM employees
GROUP BY department_id
) d ON e.department_id = d.department_id
WHERE e.salary > d.avg_salary;
总结 🎯
通过本教程,我们系统掌握了MySQL DQL的核心技能 🎓:
- SELECT基础:学会了查询特定列、使用别名和表达式
- WHERE条件:掌握了精确筛选数据的各种方法
- 排序分组:理解了ORDER BY和GROUP BY的使用场景
- HAVING:学会了过滤分组后的结果
- DISTINCT:掌握了去除重复值的技巧
- LIMIT分页:了解了实现分页查询的方法
关键收获:
- 明确查询需求再编写SQL语句
- 合理使用索引提高查询性能
- 多表连接时注意关联条件
- 大数据量分页要考虑性能优化
下一步学习建议:
- 练习复杂多表查询
- 学习EXPLAIN分析查询执行计划
- 探索窗口函数等高级查询功能
- 在实际项目中应用所学查询技巧
PS:如果你在学习过程中遇到问题,别慌!欢迎在评论区留言,我会尽力帮你解决!😄