MySQL查询技巧:复杂数据查询与聚合分析

引言

各位数据库探索者们好!今天我们要深入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的核心技能 🎓:

  1. SELECT基础:学会了查询特定列、使用别名和表达式
  2. WHERE条件:掌握了精确筛选数据的各种方法
  3. 排序分组:理解了ORDER BY和GROUP BY的使用场景
  4. HAVING:学会了过滤分组后的结果
  5. DISTINCT:掌握了去除重复值的技巧
  6. LIMIT分页:了解了实现分页查询的方法

关键收获

  • 明确查询需求再编写SQL语句
  • 合理使用索引提高查询性能
  • 多表连接时注意关联条件
  • 大数据量分页要考虑性能优化

下一步学习建议

  1. 练习复杂多表查询
  2. 学习EXPLAIN分析查询执行计划
  3. 探索窗口函数等高级查询功能
  4. 在实际项目中应用所学查询技巧

PS:如果你在学习过程中遇到问题,别慌!欢迎在评论区留言,我会尽力帮你解决!😄

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值