1

私は学生のリストとテストでの彼らの効率を作ろうとしています. データベースにはMySqlテーブルがあります

users- 学生とのテーブル

id | name
_________
1  | Joe
2  | Marry
3  | Max
4  | Anna
----------

courses- コースのあるテーブル

id | name
_____________
1  | Course 1
2  | Course 2
----------

questions- 各コースの質問表。行のcours_idは、質問がどのコースに属しているかを示します

id | cours_id | question
_________________________________
1  | 1        | Course 1 - question 1
2  | 1        | Course 1 - question 2
3  | 1        | Course 1 - question 3
4  | 1        | Course 1 - question 4
5  | 2        | Course 2 - question 1
6  | 2        | Course 2 - question 2
7  | 2        | Course 2 - question 3
8  | 2        | Course 2 - question 4

cours_invitations- すべての学生がコースへの招待状を受け取ります。行 user_id は、コースに招待されたユーザーの ID を示します。cours_id は、受講者が受講すべきコースの ID を表します。行ステータスの値が 0 の場合は、学生がコースを開始していない (保留中) ことを意味し、値が 1 の場合は、学生がコースを開始した (または完了した) ことを意味します。

id | user_id | cours_id | status
________________________________
1  | 1       | 1        | 1
2  | 1       | 2        | 0
3  | 2       | 1        | 0
4  | 3       | 1        | 1
5  | 4       | 1        | 1
6  | 4       | 2        | 1

例:ジョーとアンナはコース 1 とコース 2 に招待され、マリーとマックスはコース 1 のみに招待されました。ジョーはコース 1 を受講しましたが、コース 2 は受講しませんでした。マリーは何もせず、マックスはコース 1 を受講しました。

courses_stats- 学生が行ったコースの問題の統計です。ステータスは、回答の正確さを表します。0 は不正解、1 は正解を表します。

id | user_id | question_id | status

___________________________________
1  | 1       | 1           | 1
2  | 1       | 2           | 1
3  | 1       | 3           | 0
4  | 2       | 1           | 1
5  | 2       | 2           | 1
6  | 2       | 3           | 1
7  | 2       | 4           | 1
8  | 4       | 1           | 1
9  | 4       | 2           | 1
10 | 4       | 3           | 0
11 | 4       | 4           | 0
12 | 4       | 5           | 1
13 | 4       | 6           | 1

例:ジョーは最初のコースで 3 つの質問をしました。彼はそのコースのすべての質問を行ったわけではなく、1 つが間違っていることに注意してください。

マックスはすべての質問に正解し、アンナは最初のコースのすべての問題 (半分は不正解) と 2 番目のコースの半分 (すべて正解) を正解しました。

生徒の名前、完了したコースの割合、受講したコースの正答率 (すべてのコースではありません)、およびそれらの割合で学生を注文する可能性を含むクエリが必要です。このようなもの:

name  | completed courses | completed questions
______________________________________________
Max   |100%               |100%
Anna  |100%               |50%
Joe   |50%                |50%
Marry |0%                 |0%

このようなことは可能ですか?このクエリのテーブルにさらに行が必要ですか?

4

3 に答える 3

4

私はこれがあなたが必要とするものであるべきだと思います:

SELECT
    users.name,
    CONCAT(COUNT(
        DISTINCT CASE
        WHEN cours_invitations.status = 1 THEN
            cours_invitations.id
        ELSE
            NULL
        END
    ) / COUNT(
        DISTINCT cours_invitations.id
    ) * 100, '%') AS completed_courses,
    CONCAT(COUNT(
        DISTINCT CASE
        WHEN courses_stats.status = 1 THEN
            courses_stats.id
        ELSE
            NULL
        END
    ) / COUNT(DISTINCT questions.id) * 100, '%') AS completed_questions
FROM
    users
LEFT JOIN cours_invitations ON cours_invitations.user_id = users.id
LEFT JOIN questions ON cours_invitations.cours_id = questions.cours_id
AND cours_invitations.status = 1
LEFT JOIN courses_stats ON users.id = courses_stats.user_id
GROUP BY
    users.id
ORDER BY
    completed_courses DESC,
    completed_questions DESC

あなたへの質問として、なぜテーブル名はcours_*ではなく呼び出されるのcourse_*ですか?

于 2012-04-22T14:48:00.633 に答える
4

ここでは、テーブル スキーマとサンプル データ、およびクエリの結果を確認できます。MichaelRushton には完璧な答えがありますが、course_stats は LEFT に参加する必要があると思います。学生が cours_invitations を持っていても course_stats を持っていない場合、そのクエリはそのユーザーを返さないためです。

http://sqlfiddle.com/#!2/019dc/1

SELECT
    users.name,
    COUNT(
        DISTINCT CASE
        WHEN course_invitations.status = 1 THEN
            course_invitations.id
        ELSE
            NULL
        END
    ) / COUNT(
        DISTINCT course_invitations.id
    ) * 100 AS completed_courses,
    COUNT(
        DISTINCT CASE
        WHEN courses_stats.status = 1 THEN
            courses_stats.id
        ELSE
            NULL
        END
    ) / COUNT(DISTINCT questions.id) * 100 AS completed_questions
FROM users
INNER JOIN course_invitations ON course_invitations.user_id = users.id
INNER JOIN questions ON course_invitations.cours_id = questions.cours_id
LEFT JOIN courses_stats ON users.id = courses_stats.user_id
GROUP BY
    users.id

結果:

NAME    COMPLETED_COURSES   COMPLETED_QUESTIONS
Joe 50  25
Marry   0   100
Max 100 0
Anna    100 50
于 2012-04-22T15:06:45.667 に答える
0

「正答率」という意味だと思います。OK、count(distinct if(..))コンストラクトを巧妙に使用することで、さまざまな group-by 句を使用した複雑なサブクエリを回避できます。たとえば、このコード

count(distinct if(cours_invitations.status and courses_stats.status, 
                      NULL, questions.id)) 

条件が満たされた (個別の) 質問の数をカウントしcours_invitations.status and courses_stats.statusます。このトリックを使用すると、クエリ全体が次のようにシンプルかつエレガントになります。

select users.name, 
    count(distinct if(cours_invitations.status, 
                         NULL, 
                         cours_invitations.cours_id)) 
        / count(distinct cours_invitations.cours_id) 
        * 100 as courses_completed,
    count(distinct if(cours_invitations.status and courses_stats.status, 
                          NULL, 
                          questions.id)) 
        / count(distinct if(cours_invitations.status, 
                               NULL, 
                               questions.id)) 
        * 100 as correct_answers
from users
    left join cours_invitations on users.id = cours_invitations.user_id
    left join questions using (cours_id)
    left join courses_stats on users.id = courses_stats.user_id 
                               and questions.id = courses_stats.question_id
group by users.id
order by correct_answers

mysql の外側にパーセント記号を追加することをお勧めします。これは、mysql クエリが不必要に複雑になるためです。

于 2012-04-23T09:43:49.493 に答える