我不知道在使用sql时我是否正确地使用了以下方法,但是在这里它。
我想显示所有考试详情(考试详情(也称为会话),考试中的问题,答案,惩罚,图像,视频等)但我试图这样做的方式是一个大问题,但它不是工作时没有显示任何行。
以下是我想要为一次考试(而且只有一次考试)展示的内容:
下面显示了上述每个部分所需的字段:
考试详情
SessionId, SessionName, SessionDuration, TotalMarks, SessionWeight
考试中的所有问题
QuestionId, QuestionNo, QuestionContent, NoofAnswers, QuestionMarks, OptionId, OptionType, ReplyId, ReplyType
每个问题的所有答案,并标记每个答案值得
AnswerId, Answer, AnswerMarks
PenaltyEnabled
PenaltyAnswerId, PenaltyAnswer, PenaltyMarks
ImageId, ImageFile
VideoId VideoFile
AudioId, AudioFile
ModuleId, ModuleNo, ModuleName
StudentId
我的问题是如何编写SQL代码以便显示所有这些数据?我只需要一个大查询或许多小查询吗?我的尝试是问题的底部,但下面是数据库表格,其中显示了处理一个考试及其所有细节的详细信息。
TABLES:
学生
StudentId (PK) StudentForename StudentSurname
1 James Parker
Student_Session
SessionId (FK) StudentId (FK)
1 1
会话
SessionId (PK) SessionName SessionDuration TotalMarks SessionWeight ModuleId (FK)
1 AAA 01:00:00 30 20 1
模块
ModuleId (PK) ModuleNo ModuleName
1 CHI2513 ICT
问题
SessionId FK) QuestionId (PK) QuestionNo QuestionContent NoofAnswers QuestionMarks OptionId (FK) ReplyId (FK)
1 4 1 Question 1 1 5 1 1
1 5 2 Question 2 1 3 2 1
1 6 3 Question 3 2 6 2 2
1 7 4 Question 4 3 7 5 2
1 8 5 Question 5 1 9 5 1
答案:
AnswerId (PK) Answer QuestionId (FK)
1 A 4
2 C 5
3 A 6
4 B 6
5 B 7
6 D 7
7 E 7
8 G 8
个人答案
IndividualId (PK) AnswerId (FK) AnswerMarks
1 1 3
2 2 5
3 3 3
4 4 3
5 5 2
6 6 2
7 7 3
8 8 9
罚金
PenaltyId(PK) SessionId (FK) PenaltyEnalbed
1 1 1
PenaltyMarks
PenaltyAnswerId (PK) PenaltyAnswer PenaltyMarks QuestionId (FK)
1 B 1 4
2 C 1 4
3 A 1 5
4 B 1 5
5 D 1 5
6 C 2 6
7 D 2 6
8 A 1 7
9 C 1 7
10 F 1 7
11 G 1 7
12 A 0 8
13 B 0 8
14 C 1 8
15 D 1 8
16 E 1 8
17 F 0 8
回复
ReplyId (PK) ReplyType
1 Single
2 Multiple
Option_Table
OptionId (PK) OptionType
1 A-C
2 A-D
3 A-E
4 A-F
5 A-G
图片
ImageId (PK) ImageFile
1 ImageFile/Tulips.png
2 ImageFile/Daisys.png
视频
VideoId (PK) VideoFile
1 VideoFile/Speech.png
电台
AudioId (PK) AudioFile
1 AudioFile/Song.png
Image_Question
ImageQuestionId (PK) ImageId (FK) SessionId (FK) QuestionNo (FK)
1 1 1 2
Video_Question
VideoQuestionId (PK) VideoId (FK) SessionId (FK) QuestionNo (FK)
1 1 1 4
Audio_Question
AudioQuestionId (PK) AudioId (FK) SessionId (FK) QuestionNo (FK)
1 1 1 5
以下是我失败的尝试:
SELECT s.SessionId,
SessionName,
SessionDuration,
TotalMarks,
SessionWeight,
q.QuestionId,
q.QuestionNo,
QuestionContent,
QuestionMarks,
q.OptionId,
OptionType,
q.ReplyId,
ReplyType,
a.AnswerId,
Answer,
NoofAnswers,
AnswerMarks,
PenaltyEnabled,
PenaltyAnswerId,
PenaltyAnswer,
PenaltyMarks,
i.ImageId,
au.AudioId,
v.VideoId,
ImageFile,
AudioFile,
VideoFile,
s.ModuleId,
ModuleNo,
ModuleName,
ss.StudentId
FROM Student st
INNER JOIN Student_Session ss
ON st.StudentId = ss.StudentId
INNER JOIN Session s
ON ss.SessionId = s.SessionId
INNER JOIN Question q
ON s.SessionId = q.SessionId
INNER JOIN Answer a
ON q.QuestionId = a.AnswerId
INNER JOIN Individual_Answer ia
ON a.AnswerId = ia.AnswerId
LEFT JOIN Module m
ON s.ModuleId = m.ModuleId
LEFT JOIN Penalty p
ON q.SessionId = p.SessionId
LEFT JOIN Option_Table o
ON q.OptionId = o.OptionId
LEFT JOIN Reply r
ON q.ReplyId = r.ReplyId
LEFT JOIN Penalty_Marks pm
ON q.QuestionId = pm.QuestionId
LEFT JOIN Image_Question iq
ON q.QuestionId = iq.QuestionNo
INNER JOIN Image i
ON iq.ImageId = i.ImageId
LEFT JOIN Audio_Question aq
ON q.QuestionId = aq.QuestionNo
INNER JOIN Audio au
ON aq.AudioId = au.AudioId
LEFT JOIN Video_Question vq
ON q.QuestionId = vq.QuestionNo
INNER JOIN Video v
ON vq.VideoId = v.VideoId
WHERE s.SessionId = 1
ORDER BY q.QuestionId
更新:
下面的代码是否能够在提交问题后将QuestionId插入到Image_Question表中:(这是我在SO上找到但更新到我的表设计中的内容)
ImageQuestionToken
{
ImageToken (PK auto)
SessionId
}
Image{
ImageId
ImageFile
}
Image_Question
{
Image_QuestionId
ImageId FK references Image(ImageId)
QuestionId FK references Question(QuestionId)
}
Question
{
QuestionId (PK Auto)
QuestionNo
QuestionContent
....
}
TempImage
{
ImageToken FK references ImageQuestionToken(ImageToken)
ImageFile
}
这样的逻辑:
答案 0 :(得分:2)
虽然我不能100%确定你想要的确切结果。根据您现有的查询,问题是当您使用INNER JOIN
时,您在某些表上使用LEFT JOIN
。
在现有查询中,您使用以下内容:
LEFT JOIN Image_Question iq
ON q.QuestionId = iq.QuestionNo
INNER JOIN Image i
ON iq.ImageId = i.ImageId
LEFT JOIN Audio_Question aq
ON q.QuestionId = aq.QuestionNo
INNER JOIN Audio au
ON aq.AudioId = au.AudioId
LEFT JOIN Video_Question vq
ON q.QuestionId = vq.QuestionNo
INNER JOIN Video v
ON vq.VideoId = v.VideoId
问题是INNER JOIN
正在检查所有字段上的匹配记录,但您可能没有image
,audio
或video
表中存在的记录所以它没有返回任何东西。
根据您的详细信息,您的查询应与此类似:
select st.studentid,
s.sessionid,
s.sessionname,
s.sessionduration,
s.totalmarks,
s.sessionweight,
q.questionid,
q.questionno,
q.questioncontent,
q.noofanswers,
q.questionmarks,
q.optionid,
ot.optiontype,
q.replyid,
r.replytype,
a.answerid,
a.answer,
ia.answermarks,
p.penaltyenabled,
pm.penaltyanswerid,
pm.penaltyanswer,
pm.penaltymarks,
i.imageid,
i.imagefile,
v.videoid,
v.videofile,
ad.audioid,
ad.audiofile,
m.moduleid,
m.moduleno,
m.modulename
from Student st
inner join Student_Session ss
on st.studentid = ss.studentid
inner join session s
on ss.sessionid = s.sessionid
inner join question q
on s.sessionid = q.sessionid
inner join answer a
on q.questionid = a.questionid
inner join Individual_Answer ia
on a.answerid = ia.answerid
left join Option_Table ot
on q.optionid = ot.optionid
left join reply r
on q.replyid = r.replyid
left join module m
on s.moduleid = m.moduleid
left join Penalty p
on s.sessionid = p.sessionid
left join penalty_marks pm
on q.questionid = pm.questionid
left join image_question iq -- note I am joining on both session and question
on s.sessionid = iq.sessionid
and q.questionid = iq.questionno
left join image i -- this should be a left join not inner join
on iq.imageid = i.imageid
left join video_question vq -- note I am joining on both session and question
on s.sessionid = vq.sessionid
and q.questionid = vq.questionno
left join video v -- this should be a left join not inner join
on vq.videoid = v.videoid
left join audio_question aq -- note I am joining on both session and question
on s.sessionid = aq.sessionid
and q.questionid = aq.questionno
left join audio ad -- this should be a left join not inner join
on aq.audioid = ad.audioid
where s.SessionId = 1
order by q.QuestionId
这将返回您上面请求的所有数据。样品:
| STUDENTID | SESSIONID | SESSIONNAME | SESSIONDURATION | TOTALMARKS | SESSIONWEIGHT | QUESTIONID | QUESTIONNO | QUESTIONCONTENT | NOOFANSWERS | QUESTIONMARKS | OPTIONID | OPTIONTYPE | REPLYID | REPLYTYPE | ANSWERID | ANSWER | ANSWERMARKS | PENALTYENABLED | PENALTYANSWERID | PENALTYANSWER | PENALTYMARKS | IMAGEID | IMAGEFILE | VIDEOID | VIDEOFILE | AUDIOID | AUDIOFILE | MODULEID | MODULENO | MODULENAME |
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| 1 | 1 | AAA | 01:00:00 | 30 | 20 | 4 | 1 | Question 1 | 1 | 5 | 1 | A-C | 1 | Single | 1 | A | 3 | 1 | 1 | B | 1 | (null) | (null) | 1 | VideoFile/Speech.png | (null) | (null) | 1 | CHI2513 | ICT |
| 1 | 1 | AAA | 01:00:00 | 30 | 20 | 4 | 1 | Question 1 | 1 | 5 | 1 | A-C | 1 | Single | 1 | A | 3 | 1 | 2 | C | 1 | (null) | (null) | 1 | VideoFile/Speech.png | (null) | (null) | 1 | CHI2513 | ICT |
| 1 | 1 | AAA | 01:00:00 | 30 | 20 | 5 | 2 | Question 2 | 1 | 3 | 2 | A-D | 1 | Single | 2 | C | 5 | 1 | 3 | A | 1 | (null) | (null) | (null) | (null) | 1 | AudioFile/Song.png | 1 | CHI2513 | ICT |
| 1 | 1 | AAA | 01:00:00 | 30 | 20 | 5 | 2 | Question 2 | 1 | 3 | 2 | A-D | 1 | Single | 2 | C | 5 | 1 | 5 | D | 1 | (null) | (null) | (null) | (null) | 1 | AudioFile/Song.png | 1 | CHI2513 | ICT |
| 1 | 1 | AAA | 01:00:00 | 30 | 20 | 5 | 2 | Question 2 | 1 | 3 | 2 | A-D | 1 | Single | 2 | C | 5 | 1 | 4 | B | 1 | (null) | (null) | (null) | (null) | 1 | AudioFile/Song.png | 1 | CHI2513 | ICT |
答案 1 :(得分:1)
这些表中的外键存在问题:Image_Question,Audio_Question和Video_Question。
您使用的是QuestionNo列,该列未被表格问题索引。 我建议将列替换为QuestionId,并使用它们的值。
Image_Question
ImageQuestionId (PK) ImageId (FK) SessionId (FK) QuestionNo(FK)
1 1 1 2
Video_Question
VideoQuestionId (PK) VideoId (FK) SessionId (FK) QuestionNo(FK)
1 1 1 4
Audio_Question
AudioQuestionId (PK) AudioId (FK) SessionId (FK) QuestionNo(FK)
1 1 1 5
您的陈述应如下所示:
SELECT s.SessionId,
SessionName,
SessionDuration,
TotalMarks,
SessionWeight,
q.QuestionId,
q.QuestionNo,
QuestionContent,
QuestionMarks,
q.OptionId,
OptionType,
q.ReplyId,
ReplyType,
a.AnswerId,
Answer,
NoofAnswers,
AnswerMarks,
PenaltyEnabled,
PenaltyAnswerId,
PenaltyAnswer,
PenaltyMarks,
i.ImageId,
au.AudioId,
v.VideoId,
ImageFile,
AudioFile,
VideoFile,
s.ModuleId,
ModuleNo,
ModuleName,
ss.StudentId
FROM Student st
INNER JOIN Student_Session ss
ON st.StudentId = ss.StudentId
INNER JOIN Session s
ON ss.SessionId = s.SessionId
INNER JOIN Question q
ON s.SessionId = q.SessionId
INNER JOIN Answer a
ON q.QuestionId = a.AnswerId
INNER JOIN Individual_Answer ia
ON a.AnswerId = ia.AnswerId
LEFT JOIN Module m
ON s.ModuleId = m.ModuleId
LEFT JOIN Penalty p
ON q.SessionId = p.SessionId
LEFT JOIN Option_Table o
ON q.OptionId = o.OptionId
LEFT JOIN Reply r
ON q.ReplyId = r.ReplyId
LEFT JOIN Penalty_Marks pm
ON q.QuestionId = pm.QuestionId
LEFT JOIN Image_Question iq
ON q.QuestionNo= iq.QuestionNo
LEFT JOIN Image i
ON iq.ImageId = i.ImageId
LEFT JOIN Audio_Question aq
ON q.QuestionNo= aq.QuestionNo
LEFT JOIN Audio au
ON aq.AudioId = au.AudioId
LEFT JOIN Video_Question vq
ON q.QuestionNo= vq.QuestionNo
LEFT JOIN Video v
ON vq.VideoId = v.VideoId
WHERE s.SessionId = 1
ORDER BY q.QuestionId
更新: 您可以使用QuestionNo列后续,您只需添加索引,这样您就不必彻底检查代码。呵呵呵
我建议你加上这个:
ALTER TABLE `your_schema`.`Question`
ADD INDEX `your_idx` (`QuestionNo` ASC);
而不是这些:
LEFT JOIN Image_Question iq
ON q.QuestionId = iq.QuestionId -- from iq.QuestionNo
LEFT JOIN Image i
ON iq.ImageId = i.ImageId
LEFT JOIN Audio_Question aq
ON q.QuestionId = aq.QuestionId -- from aq.QuestionNo
LEFT JOIN Audio au
ON aq.AudioId = au.AudioId
LEFT JOIN Video_Question vq
ON q.QuestionId = vq.QuestionId -- from vq.QuestionNo
LEFT JOIN Video v
ON vq.VideoId = v.VideoId
你使用这些:
LEFT JOIN Image_Question iq
ON q.QuestionNo= iq.QuestionNo
LEFT JOIN Image i
ON iq.ImageId = i.ImageId
LEFT JOIN Audio_Question aq
ON q.QuestionNo= aq.QuestionNo
LEFT JOIN Audio au
ON aq.AudioId = au.AudioId
LEFT JOIN Video_Question vq
ON q.QuestionNo= vq.QuestionNo
LEFT JOIN Video v
ON vq.VideoId = v.VideoId
答案 2 :(得分:0)
关键问题:通常,使用外连接表的内连接不会返回任何行
我使用microsoft SQL语法进行了subqueried。希望能帮助到你。请查看底部的警告,如果愿意,请忽略create procedure语句,而只是在顶部声明并将@SessionID设置为1。
create procedure GetStuff(
@SessionID as integer
) as
declare @StudentID int -- you may need to use a different data type
select @StudentID = StudentID from Student_Session where SessionID = @SessionID
-- now we can at least remove the sessions table from the join list.
SELECT s.SessionId,
SessionName,
SessionDuration,
TotalMarks,
SessionWeight,
q.QuestionId,
q.QuestionNo,
QuestionContent,
QuestionMarks,
q.OptionId,
OptionType,
q.ReplyId,
ReplyType,
a.AnswerId,
Answer,
NoofAnswers,
AnswerMarks,
PenaltyEnabled,
PenaltyAnswerId,
PenaltyAnswer,
PenaltyMarks,
i.ImageId,
au.AudioId,
v.VideoId,
ImageFile,
AudioFile,
VideoFile,
s.ModuleId,
ModuleNo,
ModuleName,
ss.StudentId
FROM Student st
INNER JOIN Student_Session ss
ON st.StudentId = ss.StudentId
INNER JOIN Session s
ON ss.SessionId = s.SessionId
INNER JOIN Question q
ON s.SessionId = q.SessionId
INNER JOIN Answer a
ON q.QuestionId = a.AnswerId
INNER JOIN Individual_Answer ia
ON a.AnswerId = ia.AnswerId
LEFT outer JOIN Module m
ON s.ModuleId = m.ModuleId
LEFT outer JOIN Penalty p
ON q.SessionId = p.SessionId
LEFT outer JOIN Option_Table o
ON q.OptionId = o.OptionId
LEFT outer JOIN Reply r
ON q.ReplyId = r.ReplyId
LEFT outer JOIN Penalty_Marks pm
ON q.QuestionId = pm.QuestionId
-- you can't inner join off of an outer joined table, or you'll get no rows for the entire query. I've nested the query, which is bad practice but... practical for getting this monster of a query working.
LEFT outer JOIN (select c3.ImageID, c3.ImageFile from Image_Question as a1 inner join Images as b1 on a1.QuestionNo = b1.QuestionNo inner join Image as c1 on a1.ImageID = c1.ImageID)
ON q.QuestionID = iq.QuestionID
-- you can't inner join off of an outer joined table, or you'll get no rows for the entire query. I've nested the query, which is bad practice but... practical for getting this monster of a query working.
LEFT outer JOIN (select b2.AudioID, b2.AudioFile from Audio_Question as a2 inner join Audio as b2 on a2.AudioID = b2.AudioID) as aq
ON q.QuestionId = aq.QuestionNo
-- you can't inner join off of an outer joined table, or you'll get no rows for the entire query. I've nested the query, which is bad practice but... practical for getting this monster of a query working.
left outer join (select b3.VideoID, b3.VideoFile from Video_Question as a3 inner join Video as b3 on a3.QuestionID = b3.QuestionID) as vq
WHERE
st.StudentID = @StudentID
and
s.SessionId = @SessionID
ORDER BY q.QuestionId
go
警告: 您真的想要将其分解为单独的peices以便在客户端应用程序中显示。例如,您需要为Exams和ExamDetails显示主/详细信息,否则您必须在显示给用户的输出中抑制重复值。 例如,您的输出在概念上看起来像这样:
<Exam Detail Fields> <Exam Detail Fields>
first one unique What is the color of your DOG?
repeat What is the color of your CAT?
repeat What is the color of your CAR?
repeat What is the color of your HAT?
请注意左边的重复值,你必须压制它。
答案 3 :(得分:0)
好吧,小班试试吧:我的意思是: - 逐个执行查询 首先删除一些连接(删除大部分连接),然后逐个添加它们,我对我的大量查询执行相同操作以跟踪实际问题的位置,或者哪些条件对获取结果行产生了主要差异。只是一个想法。干杯!
我认为
LEFT JOIN Image_Question iq
ON q.QuestionId = iq.QuestionNo
会给你空值
当q.QuestionId从表格4开始,而iq.QuestionNo是2
INNER JOIN Image i
ON iq.ImageId = i.ImageId
由于左外连接导致的Iq字段中的所有值都为null。因此,对它们进行任何内部连接肯定会给出null结果。