mysql - 计算mysql中一行中的项目数

标签 mysql select join group-by

我有一份学生名单,显示他们是否出席了特定类(class)。

    CREATE TABLE classlist
        (`id` int, `studentid` int, `subjectid` int, `presentid` int)
    ;

    CREATE TABLE student
        (`id` int, `name` varchar(4))
    ;

    CREATE TABLE subject
        (`id` int, `name` varchar(4))
    ;

    CREATE TABLE classStatus
        (`id` int, `name` varchar(8))
    ;

    INSERT INTO classlist
        (`id`, `studentid`, `subjectid`, `presentid`)
    VALUES
        (1, 111, 1, 1),
        (2, 222, 3, 0),
        (3, 333, 2, 1),
        (4, 111, 4, 0),
        (5, 111, 1, 1),
        (6, 222, 3, 0),
        (7, 333, 2, 1),
        (8, 111, 4, 0),
        (9, 111, 4, 0),
        (10, 111, 4, 0),
        (11, 111, 1, 1),
        (12, 333, 3, 1),
        (13, 333, 2, 1),
        (14, 333, 3, 1)
    ;

    INSERT INTO student
        (`id`, `name`)
    VALUES
    (111, 'John'),
    (222, 'Kate'),
    (333, 'Matt')
    ;

    INSERT INTO subject
        (`id`, `name`)
    VALUES
    (1, 'MATH'),
    (2, 'ENG'),
    (3, 'SCI'),
    (4, 'GEO')
    ;

    INSERT INTO classStatus
        (`id`, `name`)
    VALUES
    (0, 'Absent'),
    (1, 'Present')
    ;

参见 Fiddle http://sqlfiddle.com/#!2/a2d93/5

我可以通过类似下面的内容来计算谁缺席和在场。

    SELECT
       studentid,
       students.name AS NAME,
       SUM(presentid = 1) AS present,
       SUM(presentid = 0) AS absent

    FROM classlist
    INNER JOIN student as students ON classlist.studentid=students.id

     GROUP BY studentid, NAME

但是我想知道一个学生连续上了多少节课/错过了多少节课,这样老师们就可以很容易地看到是否有人错过了很多时间或者有人因为出勤率高而得到奖励等。我看过一些帖子其中谈到了条纹,但它们似乎都不符合数据呈现给我的方式,所以我不确定如何实现这一点?

只是根据我的示例数据,条纹输出应该是清楚的。

        (1, 111, 1, 1), /* John Present 1 times in a row */
        (2, 222, 3, 0), /* Kate Absent 1 times in a row */
        (3, 333, 2, 1), /* Matt Present 1 times in a row */
        (4, 111, 4, 0), /* John Absent 1 times in a row */
        (5, 111, 1, 1), /* John Present 1 times in a row */
        (6, 222, 3, 0), /* Kate Absent 2 times in a row */
        (7, 333, 2, 1), /* Matt Present 2 times in a row */
        (8, 111, 4, 0), /* John Absent 1 times in a row */
        (9, 111, 4, 0), /* John Absent 2 times in a row */
        (10, 111, 4, 0), /* John Absent 2 times in a row */
        (11, 111, 1, 1), /* John Present 1 times in a row */
        (12, 333, 3, 1), /* Matt Present 3 times in a row */
        (13, 333, 2, 1), /* Matt Present 4 times in a row */
        (14, 333, 3, 1) /* Matt Present 5 times in a row */
        /*Showing the latest status for each user*/
        /* John Present 1 times in a row */
        /* Kate Absent 2 times in a row */
        /* Matt Present 5 times in a row */

约翰礼物 1.

凯特缺席 2.

马特礼物 5.

最佳答案

这应该给出与最后一行具有相同值的连续行的计数:

select
  classlist.studentid,
  student.name,
  classStatus.name status,
  count(*) presentcnt
from
  classlist inner join student
  on classlist.studentid=student.id
  inner join classstatus
  on classlist.presentid=classstatus.id
  inner join (
    select
      studentid,
      max(case when presentid=0 then id end)  max_0,
      max(case when presentid=1 then id end)  max_1
    from classlist
    group by studentid
  ) s
  on coalesce(classlist.id>least(max_0,max_1) and
       classlist.id<=greatest(max_0,max_1),1)
  and s.studentid=classlist.studentid
group by classlist.studentid

在子查询中,我提取了 presentid = 0 的最大 id 和 presentid = 1 的最大 id。

在外部查询中,我提取并计算 id 大于 max_0 和 max_1 中最小值且小于等于这两者中最大值的所有行。无论最后一个值是多少,这些都是与最后一个值相同的行。

如果 max_0max_1 为空,则意味着所有行只有一个值,1 或 0,我们必须获取所有这些值。如果 max_0 或 max_1 之一为空,则整个条件也将为空。在这种情况下,使用 Coalesce( condition, 1) 我将返回所有行。

请注意,我按 classlist.studentid 分组并显示一些非聚合列,但这是允许的情况,因为所有非聚合列都具有相同的值。

关于mysql - 计算mysql中一行中的项目数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14192205/

相关文章:

MySQL错误: Subquery returns more than 1 row when trying to insert values

mysql 选择行然后复制行并更新值

mysql - SQL根据最大值满足条件

mysql - Sql 显示每个组中前 10 个请求的产品

python - Pandas "join"奇怪

mysql - 左连接到 JSON 数组

java - Android和MYSQL中从listView中删除记录

php - new_link=TRUE 和 sql.safe_mode = OFF 时多个数据库连接不起作用

MySQL为每个id选择最低的时间日期

mysql - 查询 MySQL 日期时间字段中 11 个月前的任何记录