8

SQLを使用するときに以下の方法を正しく実行しているかどうかはわかりませんが、ここではそうです。

すべての試験の詳細 (試験の詳細 (セッションとも呼ばれます)、試験の問題、解答、罰則、画像、ビデオなど) を表示したい行が表示されています。

以下は、1 つの試験 (および 1 つの試験のみ) で表示したいものです。

  • 試験の詳細
  • 試験のすべての問題
  • 各質問に対するすべての回答と、各回答の価値をマークします
  • ペナルティ (有効かどうかを確認)
  • 不正解の場合は減点
  • 問題の画像
  • 質問の動画
  • 質問の音声
  • モジュールの詳細
  • 学生

以下は、上記の各セクションがデータベースから必要とするフィールドを示しています。

  • 試験の詳細

    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 コードをどのように記述する必要があるかということです。1 つの大きなクエリだけが必要なのか、それとも多数の小さなクエリが必要なのか? 私の試みは質問の一番下にありますが、以下は、1 つの試験とそのすべての詳細を処理する詳細を示すデータベース テーブルです。

表:

学生

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

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

画像_質問

   ImageQuestionId (PK) ImageId (FK) SessionId (FK)  QuestionNo (FK)
   1                    1             1                2

ビデオ_質問

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

Audio_Questions

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 

アップデート:

以下のコードは、質問が送信された後に Image_Question テーブルに QuestionId を挿入できますか: (これは 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 エントリが削除され、cascade によって 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にレコードが存在しない可能性があるため、何も返されないことです。imageaudiovideo

詳細に基づいて、クエリは次のようになります。

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

まあ、小さなシフトでそれを試してみてください: 私が意味することは:- クエリを部分的に実行します 最初にいくつかの結合を削除し (それらのほとんどを削除します)、それらを1つずつ追加します。巨大なクエリに対して同じことを行い、どこを追跡するか実際の問題、または結果の行を取得するための主な違いを生んでいる条件はどれですか。ただのアイデア。乾杯!

で思うんですけど

 LEFT JOIN Image_Question iq 
              ON q.QuestionId = iq.QuestionNo 

null値が返されます

q.QuestionId はフォーム 4 から始まり、iq.QuestionNo は 2 であるため

INNER JOIN Image i 
               ON iq.ImageId = i.ImageId 

また、左外部結合から得られた Iq フィールドのすべての値は null です。そのため、それらの内部結合は確実に null の結果をもたらします。

于 2013-01-16T05:37:16.803 に答える
0

The key problem: often, no rows will be returned using an inner join off of an outer joined table

I have subqueried, using microsoft SQL syntax. Hope it helps. See my warnings at the bottom, and ignore the create procedure statement if you like and instead just declare and set the @SessionID to 1 at the top.

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

Warnings: You will really want to break this down to seperate peices for displaying in your client application. For instance, you need a master/detail display for Exams and ExamDetails, otherwise you would have to suppress repeating values in the output shown to the user. For instance, your output would look like this, conceptually:

<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?

Note the repetitive values on the left that you would have to suppress.

于 2013-01-16T03:39:43.100 に答える