【问题标题】:mysql - find all students of a class if at least one student attendedmysql - 如果至少有一名学生参加,则查找班级的所有学生
【发布时间】:2021-01-20 07:52:18
【问题描述】:

我有四个表格来映射学生和他们参加的课程,并保存出勤信息以及开始和结束时间。

带有记录的可重现表模式:

CREATE TABLE IF NOT EXISTS `student` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
)ENGINE=InnoDB;

INSERT INTO `student` (`id`, `name`) VALUES
(1, 'student 1'),
(2, 'student 2'),
(3, 'student 3'),
(4, 'student 4'),
(5, 'student 5');


CREATE TABLE IF NOT EXISTS `class` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
)ENGINE=InnoDB;

INSERT INTO `class` (`id`, `name`) VALUES
(1, 'class 1'),
(2, 'class 2');


CREATE TABLE IF NOT EXISTS `student_class` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `student_id` int(11) DEFAULT NULL,
  `class_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  FOREIGN KEY (`student_id`) REFERENCES `student` (`id`),
  FOREIGN KEY (`class_id`) REFERENCES `class` (`id`)
)ENGINE=InnoDB;

INSERT INTO `student_class` (`id`, `student_id`, `class_id`) VALUES
(1, 1, 1),
(2, 2, 1),
(3, 3, 1),
(4, 4, 2),
(5, 5, 2);


CREATE TABLE IF NOT EXISTS `attendance` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `student_class_id` int(11) DEFAULT NULL,
  `start_time` time DEFAULT NULL,
  `end_time` time DEFAULT NULL,
  PRIMARY KEY (`id`),
  FOREIGN KEY (`student_class_id`) REFERENCES `student_class` (`id`)
)ENGINE=InnoDB;

INSERT INTO `attendance` (`id`, `student_class_id`, `start_time`, `end_time`) VALUES
(1, 1, '09:00:00', '10:00:00');

问题:

我需要列出仅显示至少有一名学生参加的班级的所有出勤情况的行, (即使其余学生的 start_time、end_time 为 null)。

这是我当前的sql:

SELECT c.id classId, sc.id mapperId, a.start_time startTime, a.end_time endTime FROM class c
JOIN student_class sc ON sc.class_id = c.id
LEFT JOIN attendance a ON a.student_class_id = sc.id;

结果应该是这样的。

classId mapperId startTime endTime
1 1 09:00:00 10:00:00
1 2 NULL NULL
1 3 NULL NULL

【问题讨论】:

    标签: mysql


    【解决方案1】:

    @user 你可以得到你正在寻找的结果集我使用你的查询的另一个实例稍微修改为子查询,像这样:

    SELECT c.id classId, 
        sc.id mapperId, 
        a.start_time startTime, 
        a.end_time endTime 
    FROM class c
    JOIN student_class sc ON sc.class_id = c.id
    LEFT JOIN attendance a ON a.student_class_id = sc.id
    WHERE `c`.`id` IN (  
      SELECT DISTINCT c.id classId
      FROM class c
      JOIN student_class sc ON sc.class_id = c.id
      JOIN attendance a ON a.student_class_id = sc.id
      )
    

    Here is a mock up of the answer on sqlfiddle.com

    【讨论】:

    • where a is not null 听起来很像内部连接
    • @Strawberry 你是对的!子查询中完全不需要LEFT JOIN 来提供所需的结果集。相应地修改了我的答案。好收获!
    • 此外,通常不需要聚合的子查询。它们可以重写为标准连接,只需将 DISTINCT 提升一个级别。
    【解决方案2】:

    只需为类 id 添加条件

    SELECT c.id classId, sc.id mapperId, a.start_time startTime, 
    a.end_time endTime FROM class c
    JOIN student_class sc ON sc.class_id = c.id
    LEFT JOIN attendance a ON a.student_class_id = sc.id
    where c.id in (select distinct sc.class_id 
                from attendance a 
                join student_class sc 
                on a.student_class_id = sc.id);
    

    【讨论】:

      【解决方案3】:

      根据你的问题答案会是这样的

        SELECT cls.id, stdclass.id AS mapperId , att.start_time ,att.end_time FROM attendance att INNER JOIN student_class stdclass ON att.student_class_id = stdclass.id INNER JOIN class cls ON stdclass.class_id = cls.id INNER JOIN student std ON stdclass.student_id = std.id 
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-02-06
        • 2021-01-15
        • 1970-01-01
        • 2019-07-12
        • 2023-03-26
        相关资源
        最近更新 更多