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 值、条件过滤)。

相关推荐
Leon-Ning Liu13 小时前
【真实经验分享】 ORA-600 [qesmaGetTblSeg1]
数据库·oracle
与数据交流的路上13 小时前
MySQL 优化 -- 相关
数据库·mysql
Rooting++13 小时前
为什么mysql的表字段的collation会自动变
数据库·mysql
Wch1G0z8A13 小时前
Google 开源了啥,让 AI Agent 碰数据库不再是定时炸弹
数据库·人工智能·开源
tedcloud12314 小时前
cc-switch评测:多AI Coding Agent管理工具详解
数据库·人工智能·sql·学习·自动化
土狗TuGou14 小时前
SQL内功笔记 · 第8篇:事务的四大特性与隔离级别
数据库·笔记·后端·sql·mysql·oracle
Nturmoils15 小时前
一台 2C2G 服务器上的 KingbaseES 安装记录
数据库
SelectDB16 小时前
从 Machine-Readable 到 Agent-Ready:面向智能体的数据库接口演进
大数据·数据库·agent
画江湖Test16 小时前
Redis 块的原理
数据库·redis·缓存·性能优化
流烟默16 小时前
国产数据库CERDB是什么以及服务启停
数据库·cerdb