SQL 多表关联与分组聚合:解密答题正确率分析

news2025/5/23 15:19:28

一、问题拆解:从业务需求到SQL逻辑

1.1 需求分析

题目要求:计算浙江大学用户在不同难度题目下的答题正确率,并按正确率升序排序。

关键分析点

  1. 数据来源
    • user_profile:存储用户信息(大学)
    • question_practice_detail:存储答题记录
    • question_detail:存储题目难度信息
  2. 筛选条件university = '浙江大学'
  3. 计算逻辑
    • 正确率 = 正确答题数 / 总答题数
    • 需按题目难度分组(difficult_level
  4. 结果要求:按正确率升序排列

1.2 示例数据与预期结果

假设各表结构及部分数据:

user_profile

device_iduniversity
1001浙江大学
1002浙江大学
1003复旦大学

question_practice_detail

device_idquestion_idresult
1001Q101right
1001Q102wrong
1002Q102right
1002Q103right

question_detail

question_iddifficult_level
Q101hard
Q102medium
Q103easy

预期结果

difficult_levelcorrect_rate
medium0.5000
hard1.0000
easy1.0000

二、核心SQL解析:多表关联与聚合计算

2.1 完整SQL语句

SELECT 
    qd.difficult_level, 
    ROUND(SUM(
        CASE 
            WHEN qpd.result = 'right' THEN 1 
            ELSE 0 
        END
    ) / COUNT(qpd.question_id), 4) AS correct_rate
FROM 
    user_profile AS up
INNER JOIN 
    question_practice_detail AS qpd 
    ON up.device_id = qpd.device_id
INNER JOIN 
    question_detail AS qd 
    ON qpd.question_id = qd.question_id
WHERE 
    up.university = '浙江大学'
GROUP BY 
    qd.difficult_level
ORDER BY 
    correct_rate ASC;

2.2 关键技术点分解

1. 三表关联策略
user_profile INNER JOIN question_practice_detail INNER JOIN question_detail
  • 作用
    • 通过device_id关联用户与答题记录
    • 通过question_id关联答题记录与题目难度
  • 选择内连接的原因
    • 仅统计实际答题的用户和题目
    • 排除未答题用户或无难度信息的题目
2. 正确率计算逻辑
ROUND(SUM(CASE WHEN qpd.result = 'right' THEN 1 ELSE 0 END) / COUNT(qpd.question_id), 4)
  • 分子SUM(CASE ...)统计正确答题数
  • 分母COUNT(qpd.question_id)统计总答题数
  • ROUND函数:保留四位小数
3. 分组与排序
GROUP BY qd.difficult_level
ORDER BY correct_rate ASC
  • 分组:按题目难度(difficult_level)分组
  • 排序:按计算出的正确率升序排列

三、SQL语法精讲

3.1 多表连接语法

table1 [INNER|LEFT|RIGHT] JOIN table2 ON condition1
[INNER|LEFT|RIGHT] JOIN table3 ON condition2
  • 本例连接类型:内连接(INNER JOIN)
  • 执行顺序:从左到右依次连接各表

3.2 聚合函数详解

函数作用
SUM(expr)计算表达式的总和
COUNT(expr)统计非NULL值的数量
ROUND(num, dec)将数值四舍五入到指定小数位数

3.3 CASE表达式

CASE 
    WHEN condition THEN value 
    ELSE default_value 
END
  • 本例应用:将布尔条件(result='right')转换为数值(1或0)

四、执行流程与数据流转

4.1 分步执行过程

步骤1:筛选浙江大学用户

WHERE up.university = '浙江大学'
  • 结果:保留user_profile中浙江大学的用户记录

步骤2:连接答题记录表

INNER JOIN question_practice_detail AS qpd 
ON up.device_id = qpd.device_id
  • 结果
    device_iduniversityquestion_idresult
    1001浙江大学Q101right
    1001浙江大学Q102wrong
    1002浙江大学Q102right
    1002浙江大学Q103right

步骤3:连接题目难度表

INNER JOIN question_detail AS qd 
ON qpd.question_id = qd.question_id
  • 结果
    device_iduniversityquestion_idresultdifficult_level
    1001浙江大学Q101righthard
    1001浙江大学Q102wrongmedium
    1002浙江大学Q102rightmedium
    1002浙江大学Q103righteasy

步骤4:分组与聚合计算

  1. 按难度分组
    • hard:Q101(1条记录,1正确)
    • medium:Q102(2条记录,1正确)
    • easy:Q103(1条记录,1正确)
  2. 计算正确率
    • hard:1/1 = 1.0000
    • medium:1/2 = 0.5000
    • easy:1/1 = 1.0000

步骤5:排序

ORDER BY correct_rate ASC
  • 最终结果:按正确率升序排列

五、性能优化策略

5.1 索引优化

-- 为user_profile添加索引
CREATE INDEX idx_university_device ON user_profile(university, device_id);

-- 为question_practice_detail添加复合索引
CREATE INDEX idx_device_question ON question_practice_detail(device_id, question_id, result);

-- 为question_detail添加索引
CREATE INDEX idx_question_difficulty ON question_detail(question_id, difficult_level);

5.2 执行计划分析

使用EXPLAIN关键字分析执行计划:

EXPLAIN
SELECT ... (SQL) ...;

关键指标解读

  • type列:期望各表连接类型为refeq_ref
  • key列:应显示使用了上述创建的索引
  • Extra列:避免出现Using filesortUsing temporary

六、常见问题与解决方案

6.1 除数为零问题

问题:若某难度题目无人作答,COUNT(qpd.question_id)为0,导致除零错误。
解决方案

-- 使用NULLIF防止除零
ROUND(SUM(CASE WHEN qpd.result = 'right' THEN 1 ELSE 0 END) / NULLIF(COUNT(qpd.question_id), 0), 4)

-- 若存在无答题记录的难度,需改用LEFT JOIN并处理NULL

6.2 正确率精度问题

问题:直接相除可能导致精度丢失。
解决方案

-- 显式转换为DECIMAL类型
ROUND(SUM(CASE WHEN qpd.result = 'right' THEN 1 ELSE 0 END) / COUNT(qpd.question_id), 4) AS correct_rate

6.3 多表连接性能问题

问题:大数据量下多表连接可能性能较差。
解决方案

  1. 确保连接字段都有索引
  2. 优先过滤数据(如先筛选浙江大学用户)
  3. 考虑使用临时表存储中间结果

七、扩展应用:分组聚合的进阶场景

7.1 计算各大学平均正确率

SELECT 
    up.university,
    ROUND(SUM(CASE WHEN qpd.result = 'right' THEN 1 ELSE 0 END) / COUNT(qpd.question_id), 4) AS avg_correct_rate
FROM ...
GROUP BY 
    up.university
ORDER BY 
    avg_correct_rate DESC;

7.2 按难度和用户分组

SELECT 
    up.device_id,
    qd.difficult_level,
    ROUND(SUM(CASE WHEN qpd.result = 'right' THEN 1 ELSE 0 END) / COUNT(qpd.question_id), 4) AS user_difficulty_rate
FROM ...
GROUP BY 
    up.device_id, 
    qd.difficult_level;

7.3 复杂条件筛选

WHERE 
    up.university IN ('浙江大学', '复旦大学')
    AND qd.difficult_level IN ('hard', 'medium')
    AND qpd.date >= '2021-08-01';

八、总结与技术要点

8.1 核心技术点回顾

  1. 多表关联策略:通过内连接整合三张表的数据
  2. 分组聚合技巧
    • 使用SUM(CASE ...)统计条件计数
    • 使用COUNT统计总数
    • 使用ROUND控制结果精度
  3. 排序与过滤:合理使用WHEREGROUP BYORDER BY
  4. 索引优化:为连接字段和过滤条件创建复合索引

8.2 技术决策树

开始
│
├── 是否需要多表关联?
│   │
│   └── 是 → 选择合适的连接类型(INNER/LEFT)
│       │
│       ├── 仅保留匹配记录 → INNER JOIN
│       │
│       └── 保留主表所有记录 → LEFT JOIN
│
├── 是否需要分组统计?
│   │
│   └── 是 → 确定分组字段和聚合函数
│       │
│       ├── 统计总数 → COUNT
│       │
│       ├── 统计条件数 → SUM(CASE ...)
│       │
│       └── 计算比例 → SUM(...)/COUNT(...)
│
├── 是否存在性能问题?
│   │
│   └── 是 → 为JOIN字段和WHERE条件创建复合索引
│
└── 结束

通过深入理解多表关联和分组聚合的原理,结合合理的索引优化,你可以高效处理各种复杂的统计分析需求,避免常见的SQL性能陷阱,提升数据处理能力。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2382113.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于 Redis 实现短信验证码登录功能的完整方案

&#x1f9f1; 一、技术栈与依赖配置 使用 Spring Boot Redis 实现短信验证码登录&#xff0c;以下是推荐的 Maven 依赖&#xff1a; <dependencies><!-- Spring Boot Web --><dependency><groupId>org.springframework.boot</groupId><ar…

电平匹配电路

1、为什么要电平匹配? 现在很多SOC器件为了降低功耗,都把IO口的电平设计成了1.8V,核电压0.85V,当这种SOC做主平台时,在做接口设计需要格外关注电平的匹配。单板中经常需要将1.8V的电平转换成3.3V或者转成5V。如果没有注意到输入和输出信号之间的电平匹配,系统就无法正常…

JavaScript 日志和调试工具箱-logger2js

原创功能丰富的 JavaScript 日志和调试工具箱&#xff0c;设计这个工具时考虑到了多种实际开发中的需求。该工具不仅提供了高效强大的日志输出显示功能&#xff0c;还包含了界面风格配置、代码格式化、事件处理、性能测试、方法调用栈输出&#xff0c;右键菜单、控制台显示控制…

zData X zStorage 为什么采用全闪存架构而非混闪架构?

点击蓝字 关注我们 最近有用户问到 zData X 的存储底座 zStorage 分布式存储为什么采用的是全闪存架构而非混闪架构&#xff1f;主要原因还是在于全闪存架构在性能和可靠性方面具有更显著的优势。zData X 的上一代产品 zData 的早期版本也使用了SSD盘作为缓存的技术架构&#x…

使用SQLite Studio导出/导入SQL修复损坏的数据库

使用SQLite Studio导出/导入SQL修复损坏的数据库 使用Zotero时遇到了数据库损坏&#xff0c;在软件中寸步难行&#xff0c;遂尝试修复数据库。 一、SQLite Studio简介 SQLite Studio是一款专为SQLite数据库设计的免费开源工具&#xff0c;支持Windows/macOS/Linux。相较于其…

Unity3D仿星露谷物语开发46之种植/砍伐橡树

1、目标 种植一棵橡树&#xff0c;从种子变成大树。 然后可以使用斧头砍伐橡树。 2、删除totalGrowthDays字段 修改growthDays的含义&#xff0c;定义每个值为到达当前阶段的累加天数。此时最后一个阶段就是totalGrowthDays的含义。所以就可以删除totalGrowthDays字段。 &…

gRPC开发指南:Visual Studio 2022 + Vcpkg + Windows全流程配置

前言 gRPC作为Google开源的高性能RPC框架&#xff0c;在微服务架构中扮演着重要角色。本文将详细介绍在Windows平台下&#xff0c;使用Visual Studio 2022和Vcpkg进行gRPC开发的完整流程&#xff0c;包括环境配置、项目搭建、常见问题解决等实用内容。 环境准备 1. 安装必要组…

高密度服务器机柜散热方案:高风压风机在复杂风道中的关键作用与选型要点

随着云计算、人工智能等技术的飞速发展&#xff0c;数据中心内服务器机柜的集成度不断攀升&#xff0c;高密度部署成为常态。然而&#xff0c;高密度意味着单位空间内服务器数量剧增&#xff0c;发热量呈指数级上升&#xff0c;传统散热方案已难以满足需求。在复杂的机柜风道环…

框架之下再看HTTP请求对接后端method

在当今的软件开发中&#xff0c;各类框架如雨后春笋般不断涌现&#xff0c;极大地提升了开发效率。以 Java 开发为例&#xff0c;Spring 框架历经多次迭代演进&#xff0c;而 Spring Boot 更是将开发便捷性提升到了新高度。如今&#xff0c;开发者只需简单引入 Maven 包&#x…

【笔记】与PyCharm官方沟通解决开发环境问题

#工作记录 2025年5月20日 星期二 背景 在此前的笔记中&#xff0c;我们提到了向PyCharm官方反馈了几个关于Conda环境自动激活、远程解释器在社区版中的同步问题以及Shell脚本执行时遇到的问题。这些问题对日常开发流程产生了一定影响&#xff0c;因此决定联系官方支持寻求解…

node.js文件系统(fs) - 创建文件、打开文件、写入数据、追加数据、读取数据、创建目录、删除目录

注意&#xff1a;以下所有示例均是异步语法&#xff01; 注意&#xff1a;以下所有示例均是异步语法&#xff01; 创建文件 node.js 允许我们在计算机本地创建文件&#xff0c;例如创建一个 word 文件&#xff1a; // 引入核心模块(fs) var fs require(fs)// API fs.writeF…

利用ffmpeg截图和生成gif

从视频中截取指定数量的图片 ffmpeg -i input.mp4 -ss 00:00:10 -vframes 1 output.jpgffmpeg -i input.mp4 -ss 00:00:10 -vframes 180 output.jpg -vframes 180代表截取180帧, 实测后发现如果视频是60fps,那么会从第10秒截取到第13秒-i input.mp4&#xff1a;指定输入视频文…

初始化一个Springboot项目

初始化一个Springboot项目 文章目录 初始化一个Springboot项目1、新建项目2、配置yml3、自定义异常4、通用相应类5、全局跨域配置6、总结 1、新建项目 首先&#xff0c;我们需要创建一个新的 Spring Boot 项目。这里我们使用 IntelliJ IDEA 作为开发工具&#xff0c;它提供了方…

YOLOv8在单目向下多车辆目标检测中的应用

大家读完觉得我有帮助记得关注&#xff01;&#xff01;&#xff01; 摘要 自动驾驶技术正逐步改变传统的汽车驾驶方式&#xff0c;标志着现代交通运输的一个重要里程碑。目标检测是自主系统的基石&#xff0c;在提高驾驶安全性、实现自主功能、提高交通效率和促进有效的应急…

Baklib构建AI就绪型知识中台实践

Baklib驱动企业知识资产重构 在数字化转型浪潮中&#xff0c;企业知识中台的构建已成为激活数据价值的关键路径。Baklib通过结构化存储与智能分类引擎&#xff0c;将分散于邮件、文档、IM工具中的碎片化信息转化为可检索、可复用的数字资产。其核心能力体现在三个维度&#xf…

JS逆向-某易云音乐下载器

文章目录 介绍下载链接Robots文件搜索功能JS逆向**函数a&#xff1a;生成随机字符串****函数b&#xff1a;AES-CBC加密****函数c&#xff1a;RSA公钥加密** 歌曲下载总结 介绍 在某易云音乐中&#xff0c;很多歌曲听是免费的&#xff0c;但下载需要VIP&#xff0c;此程序旨在“…

服务器的基础知识

什么是服务器 配置牛、运行稳、价格感人的高级计算机&#xff0c;家用电脑不能比拟的。 服务器的组成&#xff1a;电源、raid卡、网卡、内存、cpu、主板、风扇、硬盘。 服务器的分类 按计算能力分类 超级计算机 小型机AIX x86服务器&#xff08;服务器cpu架构&#xff09; …

Python连接redis

第一步安装redis Releases microsoftarchive/redis 安装时勾上所有能勾上的选项下一步即可 在CMD中pip install redis 安装redis pip install redis -i https://pypi.tuna.tsinghua.edu.cn/simple 配置redis 在redis安装目录下找到 修改 line 57 bind 0.0.0.0 line…

使用exceljs将excel文件转化为html预览最佳实践(完整源码)

前言 在企业应用中&#xff0c;我们时常会遇到需要上传并展示 Excel 文件的需求&#xff0c;以实现文件内容的在线预览。经过一番探索与尝试&#xff0c;笔者最终借助 exceljs 这一库成功实现了该功能。本文将以 Vue 3 为例&#xff0c;演示如何实现该功能&#xff0c;代码示例…

前端面经12 函数柯里化

<script>function sum(num){return function(num2){return numnum2}}console.log(sum(1)(2))</script>面试考察 只要参数够了 达到某个数量就输出 <script>let nums[]function sum(...args){nums.push(...args)if(nums.length>5){const out (nums.slice…