sql根据一个字段的值不同,关联不同的表
背景
试卷查询的时候,对应的习题有三张表,习题表(主表)、选择题表、填空题表、问答题表....
习题:XTEL_Exercises(习题)
ID |
int |
习题ID |
UploaderID |
int |
上传者ID |
Type |
int |
习题类型 0 – 选择题 1 – 问答题 2 – 填空题 |
RecordID |
int |
在实际对应类型的习题表中,习题记录的ID |
UploadTime |
int |
上传时间,以s为单位的时间戳 |
Brief |
TEXT |
习题摘要 |
选择题表:XTEL_Exer_ChoiceQuestion(选择题)
名称 |
类型 |
说明 |
ID |
int |
习题记录ID |
Stem |
TEXT |
题干 |
NumberOfOptions |
int |
选项个数 |
MaxOptions |
int |
最大选择数 |
MinOptions |
int |
最小选择数 |
Option1 |
TEXT |
选项1 |
Option2 |
TEXT |
选项2 |
Option3 |
TEXT |
选项3 |
Option4 |
TEXT |
选项4 |
Option5 |
TEXT |
选项5 |
Option6 |
TEXT |
选项6 |
ReferenceAnswer |
TEXT |
参考答案 |
填空题表:XTEL_Exer_FillupQuestion(填空题)
名称 |
类型 |
说明 |
ID |
int |
习题记录ID |
Stem |
TEXT |
题干 |
GapPos |
TEXT |
待填写答案的空白处在题干中的位置,是一串json字符串 |
GapNumber |
int |
空白个数 |
ReferenceAnswer |
TEXT |
参考答案 |
|
|
需要查询试卷:方法1:根据类型不同去分别查询,后台进行组装(暂不考虑)
方法2:sql一次性查询出来,首先想到decode、case...when....
decode
select a.*,decode(a.type,0,(select b.Stem from XTEL_Exer_ChoiceQuestion b where b.id=a.id)) from XTEL_Exercises a ---decode中只能有一列
case...when....
SELECT CASE WHEN a.type=0 THEN (SELECT b.Stem FROM XTEL_Exer_ChoiceQuestion b WHERE a.id=b.id) end case ,a.* from XTEL_Exercises a --同上
注意:decode,case...when 关联表都只能查询一列,这里明显不满足要求。
UNION ALL
之后又想到union all
SELECT b.Stem,b.ReferenceAnswerFROM XTEL_Exercises a join XTEL_Exer_ChoiceQuestion b on a.id=b.id where a.type = 0 UNION ALL SELECT c.Stem,c.ReferenceAnswer FROM XTEL_Exercises a join XTEL_Exer_EssayQuestion c on a.id=c.id AND a.type = 1
限制:union all需要每个返回的列都相同,其他地方可以加别名。但是这里我们发现选择题表需要查询的列明显多于填空题。
解决:不存在的字段赋值null,取别名。
select c.stem,c.Option1,c.Option2,c.ReferenceAnswer from XTEL_Exer2ExamPaper a join XTEL_Exercises b on a.ExerID=b.id join XTEL_Exer_ChoiceQuestion c on b.id=c.id where b.type=0 union all select c.ReferenceAnswer,null option1,null option2,c.stem from XTEL_Exer2ExamPaper a join XTEL_Exercises b on a.ExerID=b.id join XTEL_Exer_EssayQuestion c on b.id=c.id where b.type=1
思考:上面的解决方法其实都不完美,试卷创建成功后,是否可以分类查询,放入redis中,后台从redis中取值来组装数据是否更好?