【问题标题】:SQL Count Number Of Classmates For a Student Across All CoursesSQL 统计学生在所有课程中的同学人数
【发布时间】:2020-02-03 18:49:39
【问题描述】:

我有以下表格:

  • 学生:Student_ID (PK)、Student_Name
  • 课程:Course_ID (PK)、Course_Name
  • 注册:Student_ID (FK)、Course_ID (FK)

我需要 2 个查询:

  1. 为 Student 表中的每个学生 ID 计算该学生在所有课程中拥有的不同(唯一)同学的总数的查询。如果学生未注册任何课程,则应返回 0。

    例如,如果 Student_ID 123 参加了 3 门课程,并且他在每门课程中有 10 个不同的同学,我应该得到以下结果:

    Student_ID        Num_of_classmates
    -----------------------------------
    123               30
    
  2. 返回所有学生及其所有同学的 SQL 查询。学生的同学是另一名至少在同一班级注册的学生。

【问题讨论】:

  • 你的例子模棱两可。可能有一名学生至少参加了 3 门课程中的 2 门,但按照您提供的方式,该学生将被计算两次。你能澄清一下吗?
  • 如果学生注册了 3 门不同的课程,则结果将是所有课程中不同(不同)同学的数量。所以同学数不能包含重复(Student_id相同的同学)

标签: sql sql-server


【解决方案1】:

不清楚你想要哪一个:

  • 所有班级的学生总数(包括给定的学生)。
  • 不同的学生总数,因为某些同学可能在多个班级。
  • 不包括给定学生的不同学生总数(“我不是我自己的同学”)。

无论如何,这个想法基本上是两个连接和聚合:

select s.student_id,
       count(ec.student_id) as total_classmates,
       count(distinct s.student_id) as distinct_classmates,
       count(distinct case when ec.student_id <> s.student_id then ec.student_id end) as distinct_other_classmates
from student s left join
     enrollment e
     on e.student_id = s.student_id left join
     enrollment ec
     on ec.class_id = e.class_id;
group by s.student_id;

【讨论】:

  • 这很好用,但是如果学生没有注册任何课程,它会返回 -1 而不是 0。我通过将第 9 行替换为 ON (ec.class_id = e.class_id AND ec.Sid STUDENT.Sid) 并从第 4 行删除“-1”解决了这个问题
  • @Aiden 。 . .我没有考虑到这一点。我确定了答案。
【解决方案2】:

这里我只给出了第 2 部分的解决方案,因为@Gordon Linoff 已经完成了第 1 部分)并且您还修复了 -1 问题。

A 点:这里使用inner join 而不是left join,以避免在同学名中出现NULL。希望这也能增加一点帮助:)

测试数据集

if object_id('tempdb..#Student') is not null drop table #Student;
create table #Student (
    Student_ID int PRIMARY key,
    Student_Name varchar(50)
)
insert into #Student(Student_ID, Student_Name)
values (1,'Alice'), (2,'Bob'),(3,'Claire'),(4,'Danny'),(5,'Eve'),(6,'Frank');

if object_id('tempdb..#Course') is not null drop table #Course;
create table #Course (
    Course_ID int PRIMARY key,
    Course_Name varchar(50)
)
insert into #Course(Course_ID, Course_Name)
values (1,'Algorithm'), (2,'Bash'),(3,'Compiler'),(4,'Design Pattern'),(5,'Exception Handling');

if object_id('tempdb..#Enrollment') is not null drop table #Enrollment;
create table #Enrollment (
    Student_ID int,
    Course_ID int
)
insert into #Enrollment(Student_ID, Course_ID)
values (1,1),(1,3),
       (2,2),(2,3),
       (3,3),(3,4),
       (4,1),(4,4),
       (5,1),
       (6,5);  -- This Frank guy has no classmate

-- select * from #Student;
-- select * from #Course;
-- select * from #Enrollment;

2) 的解决方案

select distinct
    A.Student_Name as Student_Name,
    D.Student_Name as Classmate_Name
from #Student as A
-- Student (A) -> Enrolled Courses (B)
inner join #Enrollment as B  
    on A.Student_ID = B.Student_ID
-- Enrollment Courses (B) -> Enrolled Students in that Course (C)
inner join #Enrollment as C  
    on B.Course_ID = C.Course_ID
    and B.Student_ID <> C.Student_ID  -- exclude self
-- Classmate's names
inner join #Student as D
    on C.Student_ID = D.Student_ID
order by Student_Name, Classmate_Name;

输出

注意Frank 没有同学,也没有显示 NULL 值。

| Student_Name | Classmate_Name |
|--------------|----------------|
| Alice        | Bob            |
| Alice        | Claire         |
| Alice        | Danny          |
| Alice        | Eve            |
| Bob          | Alice          |
| Bob          | Claire         |
| Claire       | Alice          |
| Claire       | Bob            |
| Claire       | Danny          |
| Danny        | Alice          |
| Danny        | Claire         |
| Danny        | Eve            |
| Eve          | Alice          |
| Eve          | Danny          |

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-28
    • 2018-09-14
    • 2022-09-23
    • 2022-01-23
    • 1970-01-01
    相关资源
    最近更新 更多