【问题标题】:COUNT in a subquery, then SUM子查询中的 COUNT,然后是 SUM
【发布时间】:2014-04-07 22:18:58
【问题描述】:

这个应该比较简单,但是一直没搞明白。

我有一个查询,当前创建的表如下所示:

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')
;

【问题讨论】:

  • 如果只有这样的每个问题都提供 SQL Fiddle-ready DDL。我很遗憾我只能投一票。
  • +1 用于工作的 ddl。
  • 对不起,我放弃尝试理解这个架构。这是小提琴。 sqlfiddle.com/#!2/902eab/1/0
  • 抱歉,架构是 Moodle。为常见查询组装数据需要 6-7 个表连接。有人想解答我的问题吗?

标签: mysql sum subquery


【解决方案1】:

您的原始查询似乎有误。我相信 JohnDoe 以学生而不是老师的身份参加代数 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;

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-12
    • 2021-11-14
    • 1970-01-01
    • 2017-08-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多