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

相关推荐
l1t29 分钟前
DeepSeek总结的PostgreSQL使用 RDTSC 降低 EXPLAIN ANALYZE 的计时开销
数据库·postgresql
lagrahhn29 分钟前
Oracle中各个c版本介绍
数据库·oracle
知识分享小能手1 小时前
MongoDB入门学习教程,从入门到精通,在生产环境中设置MongoDB(21)
数据库·学习·mongodb
XDHCOM1 小时前
ORA-12445报错:无法更改列隐藏属性,Oracle故障修复与远程处理,网友推荐解决方案
数据库·oracle
麒麟ZHAO1 小时前
鸿蒙flutter第三方库适配 - 文件对比工具
数据库·redis·flutter·华为·harmonyos
香蕉鼠片1 小时前
Redis
数据库·redis·缓存
翻斗包菜1 小时前
第 03 章 Python 操作 MySQL 数据库实战全解
数据库·python·mysql
SPC的存折1 小时前
1、MySQL故障排查与运维案例
linux·运维·服务器·数据库·mysql
小臭希1 小时前
Redis(NoSQL数据库,Linux-Ubuntu环境下)
数据库·redis·缓存
cdcdhj1 小时前
在window下将Mongodb单机改为副本集,只用于测试环境,实际上并没有增加真的副本集
数据库·mongodb