当前位置: 首页 > news >正文

深入 MySQL SELECT 查询

深入 MySQL SELECT 查询

下面我们深入探讨 MySQL 中更复杂的 SELECT 查询操作,包括多表连接、子查询和一些高级功能。

1. 多表连接 (JOIN)

在实际应用中,数据通常分布在多个表中。连接操作允许我们根据相关列之间的关系从多个表中检索数据。

示例数据准备

首先,我们创建两个相关的表:

sql

-- 创建用户表
CREATE TABLE users (id INT PRIMARY KEY AUTO_INCREMENT,name VARCHAR(100) NOT NULL,email VARCHAR(100)
);-- 创建订单表
CREATE TABLE orders (order_id INT PRIMARY KEY AUTO_INCREMENT,user_id INT,order_date DATE,amount DECIMAL(10, 2),FOREIGN KEY (user_id) REFERENCES users(id)
);-- 插入示例数据
INSERT INTO users (name, email) VALUES
('张三', 'zhangsan@email.com'),
('李四', 'lisi@email.com'),
('王五', 'wangwu@email.com');INSERT INTO orders (user_id, order_date, amount) VALUES
(1, '2023-01-15', 150.00),
(1, '2023-02-20', 200.00),
(2, '2023-01-20', 99.99),
(3, '2023-03-05', 450.50);

内连接 (INNER JOIN)

返回两个表中匹配的行:

sql

-- 获取所有用户及其订单信息
SELECT users.id, users.name, orders.order_date, orders.amount
FROM users
INNER JOIN orders ON users.id = orders.user_id;

左连接 (LEFT JOIN)

返回左表的所有行,即使右表中没有匹配:

sql

-- 获取所有用户,即使他们没有订单
SELECT users.id, users.name, orders.order_date, orders.amount
FROM users
LEFT JOIN orders ON users.id = orders.user_id;

右连接 (RIGHT JOIN)

返回右表的所有行,即使左表中没有匹配:

sql

-- 获取所有订单,即使对应的用户不存在(但受外键约束,这种情况不会发生)
SELECT users.id, users.name, orders.order_date, orders.amount
FROM users
RIGHT JOIN orders ON users.id = orders.user_id;

多表连接

sql

-- 假设有第三个表:产品表
CREATE TABLE products (product_id INT PRIMARY KEY AUTO_INCREMENT,product_name VARCHAR(100),price DECIMAL(10, 2)
);-- 订单详情表,连接订单和产品
CREATE TABLE order_details (detail_id INT PRIMARY KEY AUTO_INCREMENT,order_id INT,product_id INT,quantity INT,FOREIGN KEY (order_id) REFERENCES orders(order_id),FOREIGN KEY (product_id) REFERENCES products(product_id)
);-- 多表连接查询
SELECT u.name,o.order_date,p.product_name,od.quantity,p.price,(od.quantity * p.price) AS total
FROM users u
INNER JOIN orders o ON u.id = o.user_id
INNER JOIN order_details od ON o.order_id = od.order_id
INNER JOIN products p ON od.product_id = p.product_id;

2. 子查询 (Subqueries)

子查询是嵌套在另一个查询中的查询,也称为内部查询或嵌套查询。

WHERE 子句中的子查询

sql

-- 找出订单金额高于平均订单金额的用户
SELECT name 
FROM users 
WHERE id IN (SELECT user_id FROM orders WHERE amount > (SELECT AVG(amount) FROM orders)
);-- 使用EXISTS检查是否存在相关订单
SELECT name 
FROM users u
WHERE EXISTS (SELECT 1 FROM orders o WHERE o.user_id = u.id AND o.amount > 200
);

FROM 子句中的子查询(派生表)

sql

-- 计算每个用户的订单总金额
SELECT u.name,COALESCE(order_totals.total_amount, 0) AS total_amount
FROM users u
LEFT JOIN (SELECT user_id, SUM(amount) AS total_amountFROM orders GROUP BY user_id
) AS order_totals ON u.id = order_totals.user_id;

SELECT 子句中的子查询(标量子查询)

sql

-- 为每个用户显示其最新订单日期
SELECT id,name,(SELECT MAX(order_date) FROM orders WHERE user_id = users.id) AS latest_order_date
FROM users;

3. 聚合函数与分组

基本分组

sql

-- 按用户分组,计算每个用户的订单总金额和订单数量
SELECT user_id,COUNT(*) AS order_count,SUM(amount) AS total_amount,AVG(amount) AS average_amount,MAX(amount) AS max_amount,MIN(amount) AS min_amount
FROM orders
GROUP BY user_id;

HAVING 子句

用于对分组后的结果进行过滤:

sql

-- 找出订单总金额超过200的用户
SELECT user_id,SUM(amount) AS total_amount
FROM orders
GROUP BY user_id
HAVING total_amount > 200;

WITH ROLLUP

生成小计和总计行:

sql

-- 按用户和日期分组,并添加小计和总计
SELECT user_id,order_date,SUM(amount) AS daily_total
FROM orders
GROUP BY user_id, order_date WITH ROLLUP;

4. 高级查询技巧

公用表表达式 (CTE)

详细讲解链接:链接

CTE 使复杂查询更易读和维护:

sql

-- 使用CTE计算每个用户的订单统计信息
WITH user_order_stats AS (SELECT user_id,COUNT(*) AS order_count,SUM(amount) AS total_amountFROM ordersGROUP BY user_id
)
SELECT u.name,uos.order_count,uos.total_amount
FROM users u
INNER JOIN user_order_stats uos ON u.id = uos.user_id
ORDER BY uos.total_amount DESC;

窗口函数

窗口函数详细讲解链接:链接

窗口函数对一组行执行计算,同时保留各行身份:

sql

-- 为每个用户的订单按金额排名
SELECT order_id,user_id,amount,RANK() OVER (PARTITION BY user_id ORDER BY amount DESC) AS amount_rank
FROM orders;-- 计算每个用户的累计订单金额
SELECT order_id,user_id,order_date,amount,SUM(amount) OVER (PARTITION BY user_id ORDER BY order_date) AS running_total
FROM orders;

5. 复杂查询示例

综合示例:找出消费最高的前3名用户及其订单详情

sql

WITH user_totals AS (SELECT user_id,SUM(amount) AS total_spentFROM ordersGROUP BY user_idORDER BY total_spent DESCLIMIT 3
),
user_orders AS (SELECT u.name,o.order_id,o.order_date,o.amount,ut.total_spent,RANK() OVER (PARTITION BY o.user_id ORDER BY o.amount DESC) AS order_rankFROM users uINNER JOIN orders o ON u.id = o.user_idINNER JOIN user_totals ut ON u.id = ut.user_id
)
SELECT name,order_id,order_date,amount,total_spent,order_rank
FROM user_orders
ORDER BY total_spent DESC, order_rank ASC;

6. 性能优化提示

SQL优化详细讲解链接:链接

  1. 索引优化:为经常用于连接和WHERE条件的列创建索引
  2. **避免SELECT ***:只选择需要的列,减少数据传输量
  3. 合理使用EXPLAIN:分析查询执行计划,找出性能瓶颈
  4. 限制结果集:使用LIMIT限制返回的行数,特别是在开发阶段
  5. 避免在WHERE子句中使用函数:这会使索引失效

sql

-- 使用EXPLAIN分析查询性能
EXPLAIN SELECT * FROM users WHERE id = 1;

通过掌握这些高级查询技术,你将能够处理更复杂的数据检索需求,并从数据库中提取有价值的见解。实践是掌握这些技能的关键,建议你尝试在自己的数据库上运行这些示例,并根据需要修改它们。

http://www.dtcms.com/a/357907.html

相关文章:

  • windows 谷歌浏览器把英文改成中文
  • 面试 八股文 经典题目 - Mysql部分(一)
  • 数据结构--栈(Stack) 队列(Queue)
  • 从单机到分布式:Python 爬虫架构演进
  • kmp 算法
  • 【MLLM】多模态理解Ovis2.5模型架构和训练流程
  • 模式组合应用-组合模式
  • 加速智能经济发展:如何助力“人工智能+”战略在实时视频领域的落地
  • 时间轴组件开发:实现灵活的时间范围选择
  • More Effective C++ 条款17: 考虑使用缓式评估(Consider Using Lazy Evaluation)
  • centos7.9的openssh漏洞修复脚本
  • 软考 系统架构设计师系列知识点之杂项集萃(137)
  • 响应式编程框架Reactor【5】
  • PostgreSQL表空间(Tablespace)作用(管理数据库对象的存储位置)(pg_default、pg_global)
  • STL库——list(类模拟实现)
  • 将LLM模型“钉”在电路板上:用电阻矩阵实现物理推理引擎
  • Nacos-3.0.3 适配PostgreSQL数据库
  • openGauss笔记
  • rabbitMQ延时队列实现,怎么保证消息的幂等
  • HTML 核心元素实战:超链接、iframe 框架与 form 表单全面解析
  • 【WDG协议栈】AUTOSAR架构下WDG模块软硬件功能详解
  • 基于单片机指纹考勤系统/智能考勤
  • ⸢ 叁 ⸥ ⤳ 默认安全:概述与建设思路
  • 【Day 33】Linux-MySQL 备份与恢复详解
  • 从分子工具到技术革新:链霉亲和素 - 生物素系统与 M13 噬菌体展示的交叉应用解析
  • 针对 “TCP 数据传输机制” 的攻击
  • vue2下拉菜单
  • 服务器托管多少钱一年?服务器托管收费标准
  • C++day2作业
  • TuringComplete游戏攻略(2.2存储器)