子查询中的COUNT,然后是SUM

时间:2014-04-07 22:18:58

标签: mysql sum subquery

这应该相对简单,但我无法弄明白。

我的查询当前创建的表格如下:

Teacher,  course,    # students in course
John Doe, Algebra 1,      3
John Doe, Algebra 2,      1
Jeff Doh, Geometry,       2

我还要计算每位老师教授的学生人数,结果如下:

Teacher,  course,     # students in course, # students with teacher
John Doe, Algebra 1,             3,               4
John Doe, Algebra 2,             1,               4
Jeff Doh, Geometry,              2,               2

但是我无法弄清楚如何制作最后一栏,该栏目总结了所有课程中老师所教的所有学生。

这是我当前的查询(我也对编写此现有查询的更好方法感兴趣)

SELECT
u.username AS 'teacher',
c.fullname AS 'course',
(SELECT COUNT(u1.username)
       FROM prefix_user u1
        JOIN prefix_user_enrolments ue1 on ue1.userid=u1.id
        JOIN prefix_enrol e1 ON e1.id=ue1.enrolid
        JOIN prefix_course c1 on c1.id = e1.courseid
        JOIN prefix_context AS ctx1 ON ctx1.instanceid = c1.id
        JOIN prefix_role_assignments AS ra1 ON ra1.contextid = ctx1.id     
        JOIN prefix_course_categories AS cc1 ON cc1.id=c1.category
       WHERE ra1.roleid="5" ### "5" = student
        AND ra1.userid=u1.id
        AND e1.courseid=c1.id
        AND c1.id=c.id) AS '# students in course'
FROM prefix_user u
JOIN prefix_user_enrolments ue on ue.userid=u.id
JOIN prefix_enrol e ON e.id=ue.enrolid
JOIN prefix_course c on c.id = e.courseid
JOIN prefix_context AS ctx ON ctx.instanceid = c.id
JOIN prefix_role_assignments AS ra ON ra.contextid = ctx.id
JOIN prefix_course_categories AS cc ON cc.id=c.category
WHERE ra.roleid="3" ### "3" = Teacher

GROUP BY c.id
ORDER BY cc.name, c.fullname

我希望我可以添加一个SUM(# students in course)列,但这不起作用。我正在使用的界面不允许我使用WITH ROLLUP。

我的架构:

CREATE TABLE prefix_user
    (`id` varchar(2), `username` varchar(11))
;

INSERT INTO prefix_user
    (`id`, `username`)
VALUES
    ('1', 'JohnDoe'),
    ('2', 'JaneDuh'),
    ('3', 'JeffDoh'),
    ('4', 'JackSprat'),
    ('5', 'WillieWinky'),
    ('6', 'DonaldDuck'),
    ('7', 'MickeyMouse')
;

CREATE TABLE prefix_user_enrolments
    (`id` varchar(2), `enrolid` varchar (4), `userid` varchar(1), `status` varchar(1))
;

INSERT INTO prefix_user_enrolments
    (`id`, `enrolid`, `userid`, `status`)
VALUES
    ('10', '1000', '1', '0'),
    ('11', '1001', '2', '0'),
    ('12', '2000', '3', '0'),
    ('13', '1002', '4', '0'),
    ('14', '2001', '5', '0'),
    ('15', '1003', '6', '0'),
    ('16', '2002', '7', '0'),
    ('17', '3000', '1', '0'),
    ('18', '3001', '7', '0')
;

CREATE TABLE prefix_enrol
    (`id` varchar(4), `status` varchar (1), `courseid` varchar(3), `roleid` varchar(1))
;

INSERT INTO prefix_enrol
    (`id`, `status`, `courseid`, `roleid`)
VALUES
    ('1000', '0', '100', '5'),
    ('1001', '0', '100', '5'),
    ('2000', '0', '200', '5'),
    ('1002', '0', '100', '5'),
    ('2001', '0', '200', '5'),
    ('1003', '0', '100', '3'),
    ('2002', '0', '200', '3'),
    ('3000', '0', '300', '3'),
    ('3001', '0', '300', '5')
;

CREATE TABLE prefix_course
    (`id` varchar(3), `fullname` varchar(8), `category` varchar(2))
;

INSERT INTO prefix_course
    (`id`, `fullname`, `category`)
VALUES
    ('100', 'Algebra1', '10'),
    ('200', 'Geometry', '10'),
    ('300', 'Algebra2', '10')
;

CREATE TABLE prefix_context
    (`id` varchar(5), `instanceid` varchar(8))
;

INSERT INTO prefix_context
    (`id`, `instanceid`)
VALUES
    ('10000', '100'),
    ('10001', '100'),
    ('20000', '200'),
    ('10002', '100'),
    ('20001', '200'),
    ('10003', '100'),
    ('20002', '200'),
    ('30000', '300'),
    ('30001', '300')
;

CREATE TABLE prefix_role_assignments
    (`id` varchar(6), `roleid` varchar(1), `contextid` varchar(5), `userid` varchar(1))
;

INSERT INTO prefix_role_assignments
    (`id`, `roleid`, `contextid`, `userid`)
VALUES
    ('100000', '5', '10000', '1'),
    ('100001', '5', '10001', '2'),
    ('200000', '5', '20000', '3'),
    ('100002', '5', '10002', '4'),
    ('200001', '5', '20001', '5'),
    ('100003', '3', '10003', '6'),
    ('200002', '3', '20002', '7'),
    ('300000', '3', '30000', '1'),
    ('300001', '5', '30001', '7')
;

CREATE TABLE prefix_role
    (`id` varchar(1), `shortname` varchar(7))
;

INSERT INTO prefix_role
    (`id`, `shortname`)
VALUES
    ('5', 'student'),
    ('3', 'teacher')
;

CREATE TABLE prefix_course_categories
    (`id` varchar(2), `name` varchar(4))
;

INSERT INTO prefix_course_categories
    (`id`, `name`)
VALUES
    ('10', 'math')
;

1 个答案:

答案 0 :(得分:1)

看起来您的原始查询可能有误。我相信John Doe作为一名学生而不是一名教师就读于代数1。我还注意到该角色存在于两个表中:prefix_enrol和prefix_role_assignments - 不确定我是否误解了某些内容,或者这是冗余数据。 在下面的尝试中,我使用子查询按courseID计算注册,其中注册的角色是学生,并按每位教师计算学生数。可能有一种更有效的方法来做到这一点,但这是我第一次尝试时所提出的:

SELECT
 t.username AS 'teacher'
 ,c.fullname AS 'course'
 ,studentCountCourse.numStudents AS '# students in course'
 ,studentCountTeach.numStudents AS '# students with teacher'
FROM prefix_enrol AS e
INNER JOIN prefix_course AS c ON c.id = e.courseid
INNER JOIN prefix_user_enrolments AS ue ON ue.enrolid = e.id
INNER JOIN prefix_user AS t ON t.id = ue.userID AND e.roleid = 3
INNER JOIN (
 SELECT
  e1.courseid
  ,count(e1.courseid) AS numStudents
 FROM prefix_enrol AS e1
 WHERE e1.roleid = 5
 GROUP BY e1.courseid) AS studentCountCourse ON studentCountCourse.courseid = c.id
INNER JOIN (
 SELECT 
  t1.id
  ,count(t1.id) AS numStudents
 FROM prefix_user AS t1
 INNER JOIN prefix_user_enrolments AS ue ON ue.userid = t1.id
 INNER JOIN prefix_enrol AS e ON e.id = ue.enrolid
 INNER JOIN prefix_enrol AS e2 ON e2.courseid = e.courseid AND e2.roleid = 5
 INNER JOIN prefix_course AS c ON c.id = e.courseid
 WHERE e.roleid = 3
 GROUP BY t1.id) AS studentCountTeach ON studentCountTeach.id = t.id
ORDER BY e.courseid;

如果我误解了您的架构,请通过解释每个表格的用途告诉我。