如何通过SQL查询直接获取三类各5道共15道测验题 替代循环校验方案
测验系统按题型固定数量随机抽题SQL实现方案
完全可以直接在SQL查询侧实现该需求,无需后端计数校验重试,相比你当前的重试方案性能更稳定,逻辑更简洁,还能避免题型分布不均场景下多次重试甚至循环超时的问题。
实现思路
- 对
quiz_type为1、2、3的题目分别做随机排序,各取5条 - 通过
UNION ALL将三个分组的结果合并,若需要打乱三种题型的展示顺序,可在外层再做一次随机排序
优化后的SQL语句
SELECT id, quiz_type FROM ( SELECT id, quiz_type FROM quiz WHERE quiz_type = '1' ORDER BY RAND() LIMIT 5 UNION ALL SELECT id, quiz_type FROM quiz WHERE quiz_type = '2' ORDER BY RAND() LIMIT 5 UNION ALL SELECT id, quiz_type FROM quiz WHERE quiz_type = '3' ORDER BY RAND() LIMIT 5 ) AS t -- 可选:如果需要全局打乱题型顺序,取消下面一行的注释 -- ORDER BY RAND()
对应PHP代码优化
你可以直接删掉原来的checkVariety方法,getRandom方法简化为如下逻辑:
public function getRandom() { $stmt = $this->db->prepare(" SELECT id, quiz_type FROM ( SELECT id, quiz_type FROM quiz WHERE quiz_type = '1' ORDER BY RAND() LIMIT 5 UNION ALL SELECT id, quiz_type FROM quiz WHERE quiz_type = '2' ORDER BY RAND() LIMIT 5 UNION ALL SELECT id, quiz_type FROM quiz WHERE quiz_type = '3' ORDER BY RAND() LIMIT 5 ) AS t -- 不需要全局打乱的话可以删掉下面这行 ORDER BY RAND() "); $stmt->execute(); $quizType = []; $data = []; while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) { $quizType[] = $row['quiz_type']; $data[] = $row['id']; } $this->startQuiz($data); return true; }
注意事项
- 请提前保证每类题型的题库量至少为5道,否则查询会返回对应类型不足5条的结果,不符合业务要求
- 若你的数据库不是MySQL,大部分主流数据库都支持类似写法,只需将随机排序函数替换为对应数据库的函数即可(比如PostgreSQL用
RANDOM(),SQL Server用NEWID())
内容的提问来源于stack exchange,提问作者SingingInTheRain
相关产品推荐
相关产品推荐

