行列转换
为啥会出现行列转换的问题呢?因为用户想看的是一张多列的大表单,但是数据库里面保存的是“单列”的数据。于是就需要做一个转换,这样客户看得更方便清晰。
SQL有一种写法可以支持这种行列转换,但是写起来比如绕,不便于理解。
所以我个人还是倾向于在前端实现转换的操作,因为可以节省后端的性能资源。
这里以成绩单为例演示一下具体的实现方式。
分析成绩单的组成
这个又爱又恨的东东想必大家都不会陌生,这是一个比较典型的需要行列转换的情景。
先回顾一下成绩单的样子:(图片来自于网络,侵删)
成绩单
分析一下,可以得到如下几个基本元素:
学科:语文、数学、物理、化学等。确定列数
学生:确定行数
年级班级:一年一班、一年二班等。分类依据
考试:期中考试、期末考试等。分类依据
成绩:确定数据内容。
元素的分类:
分类依据:指的是生成一个大表单的查询条件,同类别的数据汇总成一个大表单。
学科:确定列数,科目越多列数也就越多。
学生:确定行数,学生越多行数也就越多。
我们再看看数据库里的设计,一般会设计几个基础表和一个成绩表。
学科表
学生表
班级表
考试表
成绩表
篇幅有限,具体字段就不介绍了,说全的话也是挺复杂的。
用 vue3 + el-table 做的成绩单
行列转换后的成绩单
学科、学生、总分、平均分、最高分、最低分、名次都有了。还可以各种排序。下面我们来看看是如何实现的。
前端模拟数据
我们在前端模拟一下数据。(简化模式)
// 学科 —— 确定列
const subject = [
{ id: 1, name: '数学' },
{ id: 2, name: '语文' },
{ id: 3, name: '物理' },
{ id: 4, name: '化学' }
]
// 学生 —— 确定行
const student = [
{ id: 1, name: '张三' },
{ id: 2, name: '李四' },
{ id: 3, name: '王五' },
{ id: 4, name: '赵六' }
]
// 班级 —— 分类依据
const classes = [
{ id: 1, name: '一年一班' },
{ id: 2, name: '一年二班' }
]
// 考试 —— 分类依据
const exam = [
{ id: 1, name: '期中考试' },
{ id: 2, name: '期末考试' }
]
// 成绩 —— 确定内容
const reportCard = [
// 序号 考试ID 班级ID 学生ID 科目ID 成绩
{ id: 1, examId: 1, classId: 1, studentId: 1, subjectId: 1, score: 100 },
{ id: 2, examId: 1, classId: 1, studen