8

我不知道我在使用 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 代码才能显示所有这些数据?我只需要一个大查询还是很多小查询?我的尝试是问题的底部,但下面是数据库表,其中显示了处理一项考试及其所有详细信息的详细信息。

表格:

学生

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

罚分

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

选项表

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

视频_问题

VideoQuestionId (PK) VideoId (FK) SessionId (FK)  QuestionNo (FK)
1                      1            1                   4

音频_问题

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
}

像这样的逻辑:

  1. 用户请求问题表。服务器设置令牌并包含响应用户。
  2. 用户上传包含令牌的图片。图像存储在临时表中。
  3. 步骤 2 重复 n 次。
  4. 如果用户提交带有令牌值的问题,则会在问题表中放置一个条目并分配一个 id。TempImage 表中共享令牌的所有图像都将插入到具有现在已知 QuestionId 的图像表中。然后删除 ImageQuestionToken 条目,并级联删除 TempImage 中的临时图像。
  5. 否则用户不提交问题,则文件被删除并 ImageQuestionToken 条目被删除。
4

4 回答 4

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因此它不会返回任何内容。audiovideo

根据您的详细信息,您的查询应与此类似:

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 

请参阅SQL Fiddle with Demo

这将返回您在上面请求的所有数据。样本:

| 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 |
于 2013-01-16T10:59:24.760 回答
1

这些表中的外键存在问题:Image_Question、Audio_Question 和 Video_Question。

您正在使用未由表 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
于 2013-01-16T09:25:37.430 回答
0

关键问题:通常,使用外部联接表的内部联接不会返回任何行

我已经使用 microsoft SQL 语法进行了子查询。希望能帮助到你。请参阅底部的警告,如果您愿意,请忽略创建过程语句,而只需在顶部声明并将 @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

警告:你真的很想把它分解成单独的部分,以便在你的客户端应用程序中显示。例如,您需要为 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?

请注意左侧的重复值,您将不得不取消这些值。

于 2013-01-16T03:39:43.100 回答
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 字段中的所有值都是空的。所以它们上的任何内连接肯定会给你空结果。

于 2013-01-16T05:37:16.803 回答