【问题标题】:Return student_ids where at least one of each category返回 student_ids,其中每个类别中至少有一个
【发布时间】:2019-02-14 23:11:20
【问题描述】:

假设我们有三个表学生、作业和科目。我想返回所有学生 ID,其中该学生已完成名为 first_name = 'place' 和 last_name = 'holder' 的学生在每个科目中至少完成的一项作业。

学生桌:

Student_id | first_name | last_name
------------------------------------
     1     |   place    | holder
     2     |            |           
     3     |            |

主题:

subject_id | name
-----------------
     1     | Math
     2     | English
     3     | Science

作业:

student_id | subject_id
-----------------------
     1     |    1
     1     |    2
     1     |    3
     2     |    1
     2     |    2
     2     |    3
     3     |    1
     3     |    2

所以,在这种情况下,我希望我的查询结果是:

student_id
----------
     1
     2

我尝试了许多不同的方法,比如使用集合操作和类似的东西,但似乎没有一个能得到完全正确的结果。我不断让所有学生在学生“占位符”完成作业的任何科目中至少完成一项作业。

【问题讨论】:

  • 查看 group by 子句和 having 子句 .. 作为提示,您可以使用 having count(*) >= 1

标签: sql oracle


【解决方案1】:

您可以使用 SQL Join 来获得所需的结果。假设每个主题只有一项作业:

SELECT students.student_id FROM students
INNER JOIN assignments on assignments.student_id = students.student_id
GROUP BY students.student_id
HAVING COUNT(*) = (SELECT COUNT(*) FROM subjects)

【讨论】:

    【解决方案2】:

    加入两个表SubjectsAssignments 就足够了。您需要达到所需学生的科目数。

    with Subjects( subject_id, name) as
    (
     select 1,'Math'    from dual union all
     select 2,'English' from dual union all
     select 3,'Science' from dual
    ),   
         Assignments( student_id, subject_id) as
    (     
     select 1,1 from dual union all
     select 1,2 from dual union all 
     select 1,3 from dual union all
     select 2,1 from dual union all
     select 2,2 from dual union all
     select 2,3 from dual union all
     select 3,1 from dual union all
     select 3,2 from dual
    )
    select student_id
      from ( select count(distinct subject_id) as subject_id from Subjects ) s
      join Assignments a on a.subject_id = s.subject_id 
    
    student_id
    ----------
    1
    2 
    

    【讨论】:

      【解决方案3】:

      我没有将其他答案中的占位符名称视为查询条件,我认为这是所要求的内容的一部分。我将使用 cmets 将其分解为初步查询,以便您了解最终解决方案的构建方式:

      --this will get a 'standard' list of subjects 
      --(with at least one completed assignment by the 'standard' student)
      --to which all students will be compared
      select distinct subject_id
      from assignments a
      inner join students s
      on s.student_id = a.student_id
      where s.first_name = 'place'
      and s.last_name = 'holder';
      
      
      --cross join the students and the list above 
      --we will outer join this to the assigments table later
      select students.student_id as std_student, standard_subjects.subject_id as std_subj
      from students, 
      (select distinct subject_id
      from assignments a
      inner join students s
      on s.student_id = a.student_id
      where s.first_name = 'place'
      and s.last_name = 'holder') standard_subjects;
      
      
      --outer join this to a set of completions 
      --to compare actual completions to 
      --the standard set by the 'placeholder' student
      with completions as (select student_id, subject_id 
      from assignments
      group by student_id, subject_id
      ) 
      select std_student, std_subj, student_id
      from (select students.student_id as std_student, standard_subjects.subject_id as std_subj
      from students, 
      (select distinct subject_id
      from assignments a
      inner join students s
      on s.student_id = a.student_id
      where s.first_name = 'place'
      and s.last_name = 'holder') standard_subjects) standard
      left join completions
      on standard.std_student = completions.student_id
      and standard.std_subj = completions.subject_id;
      
      
      --sum up the completions and select only the students
      --having a completion in each 'standard' subject
      select std_student as result 
      from (
      with completions as (select student_id, subject_id 
      from assignments
      group by student_id, subject_id
      ) 
      select std_student, std_subj, student_id
      from (select students.student_id as std_student, standard_subjects.subject_id as std_subj
      from students, 
      (select distinct subject_id
      from assignments a
      inner join students s
      on s.student_id = a.student_id
      where s.first_name = 'place'
      and s.last_name = 'holder') standard_subjects) standard
      left join completions
      on standard.std_student = completions.student_id
      and standard.std_subj = completions.subject_id) comparison
      having count(student_id) = count(std_subj)
      group by std_student;
      

      【讨论】:

        猜你喜欢
        • 2012-09-13
        • 2023-03-20
        • 2022-01-13
        • 2021-03-16
        • 1970-01-01
        • 1970-01-01
        • 2019-09-22
        • 1970-01-01
        相关资源
        最近更新 更多