0

成績、課題、ユーザーの 3 つのテーブルがあります。ユーザーが持っている割り当てと完了していない割り当てを見つけられるようにしたいと考えています。ここで OUTER 結合を使用していることはわかっていますが、必要なものを複製するための正しい SQL を取得できないようです。私の表では、1 人の生徒が 1 つの課題を完了しました (1、3、1 人の生徒が 2 つの課題を完了したことを示し、1 人の生徒が 3 つの課題を完了したことを示しています。

assignment table:

assignmentID |  assignmentType | totalScore |
-------------|-----------------|------------|
      1      |   Assignment    |    100     |
      2      |   Assignment    |    100     |
      3      |   Assignment    |    100     |
      4      |   Test          |    200     |

grade table:

gradeID  |  studentID  |  assignmentID  |  grade  |
---------|-------------|----------------|---------|
   1     |      3      |       1        |    100  | 
   2     |      3      |       2        |    100  |                
   3     |      3      |       3        |    100  |                
   4     |      2      |       1        |    100  |                
   5     |      2      |       2        |    100  |                
   6     |      1      |       1        |    100  | 

student table:

studentID  | studentName |
-----------|-------------|
     1     |     John    |     
     2     |     Jane    |
     3     |     Joe     |

したがって、上記のシナリオでは、John は 1 つの割り当てが完了し、3 つが未完了であり、Jane は 2 つが完了し、2 つが未完了であり、Joe は 3 つが完了し、1 つが未完了です。

出力を次のようにします。

studentID | achievementID | grade |
----------|---------------|-------|
    1     |       1       |  100  |
    1     |       2       |  NULL |
    1     |       3       |  NULL |
    1     |       4       |  NULL |
    2     |       1       |  100  |
    2     |       2       |  100  |
    2     |       3       |  NULL |
    2     |       4       |  NULL |
    3     |       1       |  100  |
    3     |       2       |  100  |
    3     |       3       |  100  |
    3     |       4       |  NULL |

どんな助けでも大歓迎です。

4

4 に答える 4

2

別のアプローチはより高速である可能性があり、合計割り当ての計算は一度だけ行われます。

http://www.sqlfiddle.com/#!2/23408/17

select s.studentID, s.studentName,


    count(g.assignmentID) as completed,
    ta.total - count(g.assignmentID) as incomplete,

    ta.total

from student s
cross join (select count(*) as total from assignment) as ta

left join grade g 
on g.studentId = s.studentId

group by s.studentId

ただし、このクエリは生徒の課題をやみくもにカウントするため、学年の課題 ID と課題の課題 ID の間で外部キーの一貫性が必要です。

于 2012-04-30T00:54:20.637 に答える
2

これを実現する方法の 1 つを次に示します。テーブル間のすべての組み合わせを結果セットに含める必要があるためfull outer join、テーブル間でstudent実行できます。assignment学生と課題のすべての組み合わせを含む派生出力テーブルでLEFT OUTER JOIN、テーブル grade を追加して成績結果を取得します。

SQL Fiddle でデモを表示するには、ここをクリックしてください。

スクリプト:

CREATE TABLE assignment
(
    assignmentid    INT         NOT NULL
  , assignmenttype  VARCHAR(20) NOT NULL
  , totalscore      INT         NOT NULL
);

CREATE TABLE grade
(
    gradeid         INT NOT NULL
  , studentid       INT NOT NULL
  , assignmentid    INT NOT NULL
  , grade           INT NOT NULL
);

CREATE TABLE student
(
    studentid   INT         NOT NULL
  , studentname VARCHAR(20) NOT NULL
);

INSERT INTO assignment (assignmentid, assignmenttype, totalscore) VALUES
    (1, 'Assignment', 100),
    (2, 'Assignment', 100),
    (3, 'Assignment', 100),
    (4, 'Test', 200);

INSERT INTO grade (gradeid, studentid, assignmentid, grade) VALUES
    (1, 3, 1, 100),
    (2, 3, 2, 100),
    (3, 3, 3, 100),
    (4, 2, 1, 100),
    (5, 2, 2, 100),
    (6, 1, 1, 100);

INSERT INTO student (studentid, studentname) VALUES
    (1, 'John'),
    (2, 'Jane'),
    (3, 'Joe'),
    (4, 'Jill');

SELECT  sa.studentid
    ,   sa.studentname
    ,   sa.assignmentid
    ,   g.grade
FROM
(
        SELECT  s.studentid
            ,   s.studentname
            ,   a.assignmentid 
        FROM    student     s
            ,   assignment  a
)               sa 
LEFT OUTER JOIN grade g
ON              sa.studentid    = g.studentid
AND             sa.assignmentid = g.assignmentid
ORDER BY        sa.studentid
            ,   sa.assignmentid;

出力:

STUDENTID STUDENTNAME ASSIGNMENTID GRADE
--------- ----------- ------------ -----
     1    John              1       100
     1    John              2       
     1    John              3 
     1    John              4 
     2    Jane              1       100
     2    Jane              2       100
     2    Jane              3 
     2    Jane              4 
     3    Joe               1       100
     3    Joe               2       100
     3    Joe               3       100
     3    Joe               4 
     4    Jill              1 
     4    Jill              2 
     4    Jill              3 
     4    Jill              4 
于 2012-04-30T00:44:25.687 に答える
2

新しい要件: http://www.sqlfiddle.com/#!2/23408/23

select s.studentID, 

    a.assignmentID as achievementID,
    g.grade

from student s
cross join assignment a

left join grade g 
on g.studentId = s.studentId
and g.assignmentID = a.assignmentID

order by s.studentID, achievementID

出力:

STUDENTID    ACHIEVEMENTID    GRADE
1            1                100
1            2    
1            3    
1            4    
2            1                100
2            2                100
2            3    
2            4    
3            1                100
3            2                100
3            3                100
3            4    

sqlfiddle は、出力で NULL を NULL として表示しません。それにもかかわらず、上記の空の等級の基礎となる空の値は NULL です。


CROSS JOIN を使用する代わりに、テーブル カンマ テーブルを使用することもできます。しかし、これは一般的に嫌われています。テーブル カンマ テーブルを使用すると、意図しないデカルト積を簡単にコミットできます。カンマ テーブル アプローチを使用すると、3 つ以上のテーブルで生成される行数を想像してみてください。そのため、コードの意図をより明確にするために、JOIN (INNER,LEFT,CROSS,FULL,NATURAL) キーワードが SQL に導入されました。

http://www.sqlfiddle.com/#!2/23408/37

select s.studentID, 

    a.assignmentID as achievementID,
    g.grade

from (student s, assignment a)

left join grade g 
on g.studentId = s.studentId
and g.assignmentID = a.assignmentID

order by s.studentID, achievementID

テーブルコンマテーブルを使用するよりも、CROSS JOIN キーワードを使用したいと思います。CROSS JOIN はデカルト積の概念を形式化します。また、JOIN は一般に、クエリで達成したいことを形式化します。テーブルコンマテーブルでは、テーブルが内部結合操作または左結合操作などになるかどうかをクエリから推測するのは困難です。

于 2012-04-30T04:07:06.270 に答える
2

これを試してください:http://www.sqlfiddle.com/#!2/23408/15

select s.studentID, s.studentName,


    count(g.assignmentID) as completed,
    count(a.assignmentID) - count(g.assignmentID) as incomplete,

    count(a.assignmentID) as total

from student s
cross join assignment a

left join grade g 
on g.studentId = s.studentId
and g.assignmentID = a.assignmentID

group by s.studentId

出力:

STUDENTID       STUDENTNAME     COMPLETED       INCOMPLETE      TOTAL
1               John            1               3               4
2               Jane            2               2               4
3               Joe             3               1               4

サンプルデータ:

CREATE TABLE assignment
    (assignmentID int, assignmentType varchar(10), totalScore int);

INSERT INTO assignment
    (assignmentID, assignmentType, totalScore)
VALUES
    (1, 'Assignment', 100),
    (2, 'Assignment', 100),
    (3, 'Assignment', 100),
    (4, 'Test', 200);



CREATE TABLE student
    (studentID int, studentName varchar(4));

INSERT INTO student
    (studentID, studentName)
VALUES
    (1, 'John'),
    (2, 'Jane'),
    (3, 'Joe');

CREATE TABLE grade
    (gradeID int, studentID int, assignmentID int, grade int);

INSERT INTO grade
    (gradeID, studentID, assignmentID, grade)
VALUES
    (1, 3, 1, 100),
    (2, 3, 2, 100),
    (3, 3, 3, 100),
    (4, 2, 1, 100),
    (5, 2, 2, 100),
    (6, 1, 1, 100);
于 2012-04-30T00:48:09.593 に答える