SQL一对多关联查询:销售占比嵌套JSON实现与表设计评估
一、当前表结构合理性评估
你搭建的三张表已经符合关系型数据库的基础设计逻辑,整体是合格的练习用结构:
- 正确实现“企业→产品系列→单品”的层级一对多关联,没有把企业名、系列名冗余存储在单品表中,满足第一范式的基本要求
- 外键字段的设计方向正确,没有出现跨层级关联的逻辑错误
目前可优化的细节:
- 三张表的ID字段需要明确标注为主键,避免插入重复ID导致关联错乱
- 外键关联字段要加外键约束,防止出现“单品关联不存在的产品系列ID”这类脏数据
total_manufactured和sold字段要加非空约束、取值大于0的检查约束,匹配生产数据的真实校验规则- 如果后续需要按时间维度统计销售,当前表结构缺少日期字段,可根据练习需求补充
二、可直接落地的SQL查询逻辑
先把统计规则拆解为可执行的步骤,完全匹配要求:
规则拆解:
- 计算单个单品的销售率:已售数量 / 总生产数量
- 单个产品系列的销售率:该系列下所有单品销售率的平均值
- 企业整体销售占比:该企业下所有产品系列销售率的平均值
- 适配你已掌握Python处理查询结果的习惯,不在SQL层面拼接嵌套JSON,通过平层查询拿结果,Python侧组装即可,兼容性更强
-- 第一步:获取每个企业下属各产品系列的销售率 SELECT c.Name AS company_name, ps.Name AS series_name, -- 保留2位小数匹配示例精度 ROUND(AVG(p.sold * 1.0 / p.total_manufactured), 2) AS series_sale_rate FROM PRODUCTS p INNER JOIN PRODUCTSERIES ps ON p.PRODUCTSERIES_FK = ps.ID INNER JOIN COMPANY c ON ps.COMPANY_FK = c.ID GROUP BY c.ID, c.Name, ps.ID, ps.Name
注意:计算时乘以1.0是为了规避部分数据库的整数除法逻辑,避免两个整数相除直接取整丢失浮点数精度。
执行上述查询会得到平层的系列维度统计结果,例如:
| company_name | series_name | series_sale_rate |
|---|---|---|
| MICROSOFT | OFFICE | 0.09 |
| MICROSOFT | WINDOWS | 0.09 |
| APPLE | IPHONE | 0.09 |
| APPLE | MACBOOK | 0.09 |
| SAMSUNG | GALAXY | 0.09 |
| SAMSUNG | GALAXYNOTE | 0.09 |
-- 第二步:获取每个企业的整体销售占比 SELECT c.Name AS company_name, ROUND(AVG(series.series_sale_rate), 2) AS total_sales_pct FROM ( -- 嵌套上一步的系列维度统计逻辑 SELECT ps.COMPANY_FK, ROUND(AVG(p.sold * 1.0 / p.total_manufactured), 2) AS series_sale_rate FROM PRODUCTS p INNER JOIN PRODUCTSERIES ps ON p.PRODUCTSERIES_FK = ps.ID GROUP BY ps.ID, ps.COMPANY_FK ) series INNER JOIN COMPANY c ON series.COMPANY_FK = c.ID GROUP BY c.ID, c.Name
在Python侧将两个查询的结果按企业名称关联,即可组装出你需要的嵌套JSON结构。
三、对应知识点学习指引
- 基础聚合能力:掌握
AVG、ROUND、GROUP BY的使用,这是分层计算不同维度平均值的核心,是SQL查询的必会基础 - 多表关联逻辑:熟悉
JOIN的关联条件匹配规则,理清层级表的关联关系 - 多层查询优化:后续可学习公用表表达式(CTE),简化多层嵌套的查询写法,提升代码可读性
- 表结构约束设计:掌握主键、外键、检查约束的使用方法,搭建更健壮的表结构
内容的提问来源于stack exchange,提问作者PJ47
相关产品推荐
相关产品推荐

