Question

my SQL is a bit rusty after 2 years of not having studied it, so I can't find a way to do this.

I need to get some data from a Moodle database, namely some averages of feedback tests where students rate their teachers.

This SQL query:

SELECT mdl_course.id, mdl_user.username FROM mdl_course
INNER JOIN mdl_context ON mdl_context.instanceid = mdl_course.id
INNER JOIN mdl_role_assignments ON mdl_context.id = mdl_role_assignments.contextid
INNER JOIN mdl_role ON mdl_role.id = mdl_role_assignments.roleid
INNER JOIN mdl_user ON mdl_user.id = mdl_role_assignments.userid
WHERE mdl_role.id = 3

returns something like this, a table with each course and its teacher as assigned.

COURSE_ID TEACHER   
2          john
3          mary
4          john

Now, my second SQL is like this:

SELECT mdl_feedback.course, AVG(mdl_feedback_value.value) as average
FROM mdl_feedback_value 
INNER JOIN mdl_feedback_item ON mdl_feedback_value.item = mdl_feedback_item.id 
INNER JOIN mdl_feedback ON mdl_feedback.id = mdl_feedback_item.feedback
INNER JOIN mdl_feedback_completed ON mdl_feedback.id = mdl_feedback_completed.feedback
INNER JOIN mdl_user ON mdl_feedback_completed.userid = mdl_user.id
GROUP BY mdl_feedback.course

COURSE    AVERAGE   
2          3.5
3           3
4          3.25

What I want is to combine those 2 SQL queries into one that goes like this, using COURSE/COURSE_ID as the key

TEACHER    AVERAGE
john         3,375   <--- avg of 3,5 and 3,25 from each of john's courses
mary         3       <--- she has just one course so no math here

I'm not sure on how to go for this, so I appreciate a bit of help :) As I said, I haven't used SQL for a while so I'm not keen in those JOIN thingies, maybe I have to use them as I have used them here.

I'm using MySQL 5.5.33, and although this is related to Moodle, the answer is not really Moodle-centered as the only thing important here is what tables as the output from both queries.

Thanks

Was it helpful?

Solution

If you take each of the subqueries and then try to JOIN them, it should work. I added a third field to help you see the detail of how the score was created.

SELECT username, AVG(average) AS average
  , GROUP_CONCAT(CONCAT('Course: ', teachers.course_id,' with score ', COALESCE(average,'No Score Found'))) AS detail
FROM (
    SELECT mdl_course.id AS course_id, mdl_user.username AS username
    FROM mdl_course
    INNER JOIN mdl_context ON mdl_context.instanceid = mdl_course.id
    INNER JOIN mdl_role_assignments ON mdl_context.id = mdl_role_assignments.contextid
    INNER JOIN mdl_role ON mdl_role.id = mdl_role_assignments.roleid
    INNER JOIN mdl_user ON mdl_user.id = mdl_role_assignments.userid
    WHERE mdl_role.id = 3 ) AS teachers
LEFT JOIN (
    SELECT mdl_feedback.course AS course_id, AVG(mdl_feedback_value.value) as average
    FROM mdl_feedback_value 
    INNER JOIN mdl_feedback_item ON mdl_feedback_value.item = mdl_feedback_item.id 
    INNER JOIN mdl_feedback ON mdl_feedback.id = mdl_feedback_item.feedback
    INNER JOIN mdl_feedback_completed ON mdl_feedback.id = mdl_feedback_completed.feedback
    INNER JOIN mdl_user ON mdl_feedback_completed.userid = mdl_user.id
    GROUP BY mdl_feedback.course) AS scores
  ON teachers.course_id = scores.course_id
GROUP BY username

OTHER TIPS

I am Trying to use a temp table to store the two different query result sets and then later i am querying the temp table to get the average of the teacher. Hope this works.

CREATE TABLE #TEMP
(
COURSE_ID int,
TEACHER varchar(100),
COURSE int,
AVERAGE int
)
--- Inserting the course_id and Teahcer data----

INSERT INTO #TEMP
(
COURSE_ID,
TEACHER
)
SELECT mdl_course.id, mdl_user.username FROM mdl_course
INNER JOIN mdl_context ON mdl_context.instanceid = mdl_course.id
INNER JOIN mdl_role_assignments ON mdl_context.id = mdl_role_assignments.contextid
INNER JOIN mdl_role ON mdl_role.id = mdl_role_assignments.roleid
INNER JOIN mdl_user ON mdl_user.id = mdl_role_assignments.userid
WHERE mdl_role.id = 3

-- Inserting the course and average data---
INSERT INTO #TEMP
(
COURSE,
AVERAGE
)
SELECT mdl_feedback.course, AVG(mdl_feedback_value.value) as average
FROM mdl_feedback_value 
INNER JOIN mdl_feedback_item ON mdl_feedback_value.item = mdl_feedback_item.id 
INNER JOIN mdl_feedback ON mdl_feedback.id = mdl_feedback_item.feedback
INNER JOIN mdl_feedback_completed ON mdl_feedback.id = mdl_feedback_completed.feedback
INNER JOIN mdl_user ON mdl_feedback_completed.userid = mdl_user.id
GROUP BY mdl_feedback.course


--- Querying the # temp table for the average and teacher---

SELECT TEACHER, AVG(AVERAGE)
FROM #TEMP
GROUP BY TEACHER

You could try joining the two queries using

INNER JOIN mdl_course ON mdl_feedback.course = mdl_course.id

Please see if this combined query works:

SELECT mdl_user.username, AVG(mdl_feedback_value.value) as average
FROM mdl_feedback_value 
INNER JOIN mdl_feedback_item ON mdl_feedback_value.item = mdl_feedback_item.id 
INNER JOIN mdl_feedback ON mdl_feedback.id = mdl_feedback_item.feedback
INNER JOIN mdl_feedback_completed ON mdl_feedback.id = mdl_feedback_completed.feedback
INNER JOIN mdl_user ON mdl_feedback_completed.userid = mdl_user.id
INNER JOIN mdl_course ON mdl_feedback.course = mdl_course.id
INNER JOIN mdl_context ON mdl_context.instanceid = mdl_course.id
INNER JOIN mdl_role_assignments ON mdl_context.id = mdl_role_assignments.contextid
INNER JOIN mdl_role ON mdl_role.id = mdl_role_assignments.roleid
INNER JOIN mdl_user ON mdl_user.id = mdl_role_assignments.userid
WHERE mdl_role.id = 3
GROUP BY mdl_user.username;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top