【问题标题】:Show "0" results with COUNT(course.id)使用 COUNT(course.id) 显示“0”个结果
【发布时间】:2019-09-10 02:57:20
【问题描述】:

我有一个查询可以正确计算平台内每门课程的学生人数,但它不返回学生人数 = 0 的结果。如何修改以下查询以包含此内容?

SQL:

/*  MSSQL
    Name: Courses using the TDC themes with student enrolment count
    Description: Returns a list of courses using a TDC theme and the number of enrolled students in each course.
*/

select
    concat('<a target="_blank" href="%%wwwroot%%/course/index.php?categoryid=',cat.id,'">', cat.name,'</a>') as "Category",
    concat('<a target="_new" href="%%wwwroot%%/course/view.php?id=',course.id,'">',course.fullname,'</a>') as "Course",
    course.theme as "Theme",
    count(course.id) as "Students"
from prefix_course as course
    join prefix_context as context on context.instanceid = course.id
    join prefix_role_assignments as ra on ra.contextid = context.id
    join prefix_course_categories as cat on cat.id = course.category
where context.contextlevel = 50 and ra.roleid = 5 and course.theme like 'tdc%'
group by cat.id, cat.name, course.id, course.fullname, course.theme
order by cat.name

实际结果:

| Category  | Course             | # of Students |
|-----------|--------------------|---------------|
| Baking    | Baking 101         | 7             |
| IT        | Intro to Excel     | 9             |

预期结果:

| Category  | Course             | # of Students |
|-----------|--------------------|---------------|
| Baking    | Baking 101         | 7             |
| IT        | Web Programming    | 0             |
| IT        | Intro to Excel     | 9             |
| Chemistry | Chemical Reactions | 0             |

我已经搜索了一些关于 SO 的问题(例如 here),但无法根据我的情况翻译答案。

【问题讨论】:

  • 您的一个表没有匹配的数据,请尝试在 prefix_role_assignments 上使用左连接
  • Protip:不要在 SQL 中生成视图级数据。在这种情况下,您将在 SQL 中生成 HTML。不要这样做,因为从长远来看,这会使您的代码的可维护性大大降低——如果您想从非 Web 应用程序运行查询怎么办?要点是:遵循单一职责原则。
  • @metal 不起作用,因为如果 prefix_course 中有任何记录,您最终会得到一个计数。但他要求的是计数为 0 的实例。我不确定这个问题的格式是否正确。 OP - 如果您期望 id 计数为 0(又名不存在),为什么会在 prefix_course 中有记录?
  • @kjmerf,啊,我明白你的意思了。我可能不得不重新考虑我是如何创建这个查询的。它最初是作为一个没有学生人数的查询(即,只有类别、课程和主题信息)开始的,这是数据库中一个更简单的查询。您对如何执行此操作有任何建议吗?我将添加一个 sqlfiddle 链接以包含 db 架构和一些虚拟数据。
  • 有了预期的结果和样本数据应该是可行的。

标签: sql sql-server


【解决方案1】:

通过这种方式分组:GROUP BY ALL。这是 cte6 答案的替代方案。

调整后的查询:

select
    concat('<a target="_blank" href="%%wwwroot%%/course/index.php?categoryid=',cat.id,'">', cat.name,'</a>') as "Category",
    concat('<a target="_new" href="%%wwwroot%%/course/view.php?id=',course.id,'">',course.fullname,'</a>') as "Course",
    course.theme as "Theme",
    count(course.id) as "Students"
from prefix_course as course
    join prefix_context as context on context.instanceid = course.id
    join prefix_role_assignments as ra on ra.contextid = context.id
    join prefix_course_categories as cat on cat.id = course.category
where context.contextlevel = 50 and ra.roleid = 5 and course.theme like 'tdc%'
group by all cat.id, cat.name, course.id, course.fullname, course.theme
order by cat.name

【讨论】:

  • 不错!这是一个进步,但它现在显示了大量不应该出现的数据 - 它显示了大约 1000 条记录,而不是我添加到 OP 的预期结果。
【解决方案2】:

如果您将 prefix_course 表移动到左外连接并使用 sum(if(course.id is null,0,1)) 而不是 sum 它应该可以工作:

select
    concat('<a target="_blank" href="%%wwwroot%%/course/index.php?categoryid=',cat.id,'">', cat.name,'</a>') as "Category",
    concat('<a target="_new" href="%%wwwroot%%/course/view.php?id=',course.id,'">',course.fullname,'</a>') as "Course",
    course.theme as "Theme",
    sum(iif(course.id is null,0,1)) as "Students"
from prefix_context as context 
    inner join prefix_role_assignments as ra on ra.contextid = context.id
    inner join prefix_course_categories as cat on cat.id = course.category
    left outer join prefix_course as course on context.instanceid = course.id and course.theme like 'tdc%'
where context.contextlevel = 50 and ra.roleid = 5
group by cat.id, cat.name, course.id, course.fullname, course.theme
order by cat.name

【讨论】:

  • 不幸的是,这并不能解决问题 - 它显示与 count(course.id) 相同的数据集。
  • 它还会显示计数为 0 的记录,因为使用了左外连接。而在 SQL Server 中,条件是 IIF 而不是 IF(或者你可以用例)。
  • 啊,我的错。只是认为IIF是一个错字!我不得不将第二个内部连接移到 from 的末尾以解决“无法绑定多部分标识符“course.category”。”,但这仍然产生与我的“实际结果”完全相同的数据集。
  • 是的,你是对的。作为 where 子句的一部分,有一个“and course.theme like 'tdc%'”。这基本上使左外连接表现得像内连接。我已对其进行了更改并将其作为内部连接条件的一部分移动。
  • 嘿@cte6,我发布了一条评论,其中包含解决此问题的代码。您的总和解决方案对实现这一目标有很大帮助!
【解决方案3】:

在解决这个难题一段时间后,我意识到我的问题在于选择我认为执行此任务所需的表。我用下面的select 语句和表格解决了这个问题。我还使用了不同的虚拟数据(抱歉),所以我用新的虚拟数据更新了我的 OP:

select
    concat('<a target="_blank" href="%%wwwroot%%/course/index.php?categoryid=',cat.id,'">', cat.name,'</a>') as "Category",
    concat('<a target="_new" href="%%wwwroot%%/course/view.php?id=',c.id,'">',c.fullname,'</a>') as "Course",
    c.theme as Theme,
    sum(iif(r.id is null,0,1)) as '# of Students'
from prefix_user as u
    join prefix_role_assignments as ra on u.id = ra.userid
    left outer join prefix_role as r on ra.roleid = r.id and r.id = 5 -- student role id in moodle.
    join prefix_context as ct on ra.contextid = ct.id
    join prefix_course as c on c.id = ct.instanceid and ct.contextlevel = 50 -- 'course' context type.
    join prefix_course_categories as cat on cat.id = c.category and c.theme like 'tdc%'
group by cat.id, c.id, cat.name, c.fullname, c.theme

表: prefix_course_categories:

|  id | name      |
|-----|-----------|
| 1   | Baking    |
| 2   | Chemistry |
| 3   | IT        |

前缀课程:

|  id | name               | categoryid  | theme        |
|-----|--------------------|-------------|--------------| -- prefix_course.categoryid =
| 8   | Baking 101         | 1           | tdcemuteal   | -- prefix_course_categories.id
| 90  | Web Programming    | 2           | NULL         |
| 287 | Intro to Excel     | 2           | tdcemuaqua   |
| 396 | Chemical Reactions | 3           | tdcemuorange |

prefix_user:

|  id  |
|------|
| 1    |
| 2    |
| 5    |
| 8    |
| 15   |
| 16   |
| 20   |
| 23   |
| 77   |
| 99   |
| 303  |
| 879  |
| 959  |
| 1235 |

前缀角色:

|  id | name                |
|-----|---------------------|
| 1   | Manager             |
| 2   | Course Creator      |
| 3   | Teacher             |
| 4   | Non-Editing Teacher |
| 5   | Student             |

prefix_role_assignments:

|  id |  contextid | userid | roleid |
|-----|------------|--------|--------| -- prefix_role_assignments.contextid = 
| 1   | 1          | 879    | 5      | -- prefix_context.id
| 2   | 2          | 303    | 5      | 
| 3   | 3          | 5      | 5      | -- prefix_role_assignments.userid = 
| 4   | 4          | 15     | 6      | -- prefix_user.id
| 5   | 5          | 57     | 5      |
| 6   | 6          | 23     | 5      | -- prefix_role_assignments.roleid = 
| 7   | 7          | 959    | 5      | -- prefix_role.id
| 8   | 8          | 99     | 5      |
| 9   | 9          | 879    | 5      |
| 10  | 10         | 303    | 5      |
| 11  | 11         | 5      | 5      |
| 12  | 12         | 15     | 5      |
| 13  | 13         | 57     | 5      |
| 14  | 14         | 23     | 5      |
| 15  | 15         | 959    | 5      |
| 16  | 16         | 77     | 5      |
| 17  | 17         | 1235   | 5      |
| 18  | 18         | 8      | 1      |
| 19  | 19         | 23     | 7      |
| 20  | 20         | 287    | 7      |
| 21  | 21         | 287    | 7      |
| 22  | 22         | 287    | 7      |
| 23  | 23         | 287    | 7      |
| 24  | 24         | 699    | 7      |

prefix_context:

|  id |  contextlevel | instanceid |
|-----|---------------|------------|
| 1   | 50            | 8          | -- prefix_context.instanceid =
| 2   | 50            | 8          | -- prefix_course.id 
| 3   | 50            | 8          |
| 4   | 50            | 8          | -- instanceid where contextlevel = 50 are courses that students enrol into.
| 5   | 50            | 8          |
| 6   | 50            | 8          |
| 7   | 50            | 8          |
| 8   | 90            | 8          |
| 9   | 50            | 287        |
| 10  | 50            | 287        |
| 11  | 50            | 287        |
| 12  | 50            | 287        |
| 13  | 50            | 287        |
| 14  | 50            | 287        |
| 15  | 50            | 287        |
| 16  | 50            | 287        |
| 17  | 50            | 287        |
| 18  | 60            | 287        |
| 19  | 50            | 396        |
| 20  | 20            | 287        |
| 21  | 60            | 287        |
| 22  | 10            | 287        |
| 23  | 80            | 287        |
| 24  | 50            | 699        |

【讨论】:

    猜你喜欢
    • 2015-12-15
    • 1970-01-01
    • 1970-01-01
    • 2020-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-07-06
    • 2011-07-23
    相关资源
    最近更新 更多