SQL 面试题解析:如何用多表查询写用户订单统计?

在 SQL 面试中,多表查询 + 业务场景统计 是高频考点。常见的题目之一就是:

已知用户表(user)、订单表(order),如何统计每个用户的订单数量和总金额?

这类问题不仅考察语法掌握,还考察你对业务逻辑的抽象与 SQL 优化能力。本文带你逐步解析。

一、题目背景

假设有两张表:

用户表:存储用户的基本信息(用户 id、姓名等)。

订单表:存储订单详情(订单 id、用户 id、订单金额等)。

需求:查询每个用户的订单数和订单总金额。

二、解法思路

明确关联关系

用户表和订单表是一对多关系。

需要通过 user.id = order.user_id 进行关联。

选择合适的 JOIN

如果只统计有订单的用户,用 INNER JOIN。

如果希望统计所有用户,即使没有订单也显示,用 LEFT JOIN。

用聚合函数做统计

COUNT 统计订单数量。

SUM 统计订单金额。

搭配 GROUP BY 按用户分组。

三、SQL 实现

  1. 仅统计有订单的用户

SELECT u.id, u.name,

COUNT(o.id) AS order_count,

SUM(o.amount) AS total_amount

FROM user u

INNER JOIN orders o ON u.id = o.user_id

GROUP BY u.id, u.name;

  1. 包含所有用户(无订单显示为 0)

SELECT u.id, u.name,

COUNT(o.id) AS order_count,

IFNULL(SUM(o.amount), 0) AS total_amount

FROM user u

LEFT JOIN orders o ON u.id = o.user_id

GROUP BY u.id, u.name;

IFNULL 的作用是防止出现 NULL,比如用户没有订单时总金额为 0。

四、面试延伸问题

在实际面试中,考官往往会追问:

如何统计近 30 天的订单?

WHERE o.order_date >= DATE_SUB(CURDATE(), INTERVAL 30 DAY)

如何只统计已支付的订单?

WHERE o.status = 'paid'

如果要统计订单均价呢?

AVG(o.amount)

能否只显示订单数大于 5 的用户?

HAVING COUNT(o.id) > 5

五、优化思路

建立索引

在 orders.user_id 上加索引,加快关联查询。

在 orders.order_date 上加索引,加快时间区间过滤。

避免不必要的函数

尽量不要在 WHERE 条件里对字段直接用函数,否则索引失效。

大数据量时分批查询

如果订单数据量非常大,可以用分页或分区表。

六、总结

这类题目考察三个核心点:

多表关联: INNER JOIN vs LEFT JOIN。

聚合统计: COUNT / SUM / AVG 等函数结合 GROUP BY。

业务扩展: 加上时间区间、订单状态、HAVING 过滤。

一句话记住面试答题思路:

先确定表关系,再选 JOIN 类型,用聚合函数统计,最后考虑边界情况(无订单用户、NULL 值、条件过滤)。

相关推荐
fen_fen1 天前
Oracle建表语句示例
数据库·oracle
砚边数影1 天前
数据可视化入门:Matplotlib 基础语法与折线图绘制
数据库·信息可视化·matplotlib·数据可视化·kingbase·数据库平替用金仓·金仓数据库
orange_tt1 天前
Djiango配置Celery
数据库·sqlite
云小逸1 天前
【nmap源码学习】 Nmap网络扫描工具深度解析:从基础参数到核心扫描逻辑
网络·数据库·学习
肉包_5111 天前
两个数据库互锁,用全局变量互锁会偶发软件卡死
开发语言·数据库·c++
霖霖总总1 天前
[小技巧64]深入解析 MySQL InnoDB 的 Checkpoint 机制:原理、类型与调优
数据库·mysql
此刻你1 天前
常用的 SQL 语句
数据库·sql·oracle
それども1 天前
分库分表的事务问题 - 怎么实现事务
java·数据库·mysql
·云扬·1 天前
MySQL Binlog 配置指南与核心作用解析
数据库·mysql·adb
天空属于哈夫克31 天前
Java 版:利用外部群 API 实现自动“技术开课”倒计时提醒
数据库·python·mysql