【问题标题】:SQL query to print the name of the students who are a part of the symmetric pairSQL 查询以打印属于对称对的学生的姓名
【发布时间】:2019-12-04 18:01:46
【问题描述】:

鉴于表 studentma​​thematics_marksscience_marks

学生

  • student_id(主键)|小号
  • 学生姓名                 | varchar(30)

ma​​thematics_marks

  • student_id(主键)|小号
  • 得分                             |浮动 (5,2)

科学标记

  • student_id(主键)|小号
  • 得分                             |浮动 (5,2)

如果该学生在科学中获得的分数与其他学生在数学中获得的分数相等,并且在数学中获得的分数与该学生获得的分数相同,则该学生被称为对称对的一部分其他理科学生。

我正在尝试通过以下查询解决上述问题:

SELECT s.student_name 
FROM student s
LEFT JOIN (mathematics_marks m CROSS JOIN science_marks sc) 
    ON (s.student_id = m.student_id AND m.student_id = sc.student_id)
    WHERE EXISTS(SELECT * FROM mathematics_marks m 
                    WHERE sc.score=m.score 
                    AND m.score=sc.score)
    ORDER BY student_name;

我没有得到正确的输出。谁能帮我解决我哪里出错了?

【问题讨论】:

  • 为每个主题设置单独的表格似乎是糟糕的设计。 :-(

标签: mysql


【解决方案1】:

以一种非常简单的方式

select s.student_name 'student_name'
from student s
inner join mathematics_marks m
on m.student_id = s.student_id
inner join science_marks sc 
on sc.student_id = s.student_id
where m.score in ( select score from science_marks ) and 
      sc.score in ( select score from mathematics_marks )
ORDER BY student_name;

【讨论】:

  • 请说明您想要什么?
【解决方案2】:

我会这样做:

SELECT s.student_name
FROM student s
LEFT JOIN mathematics_marks m ON m.student_id = s.student_id
LEFT JOIN science_marks sc ON sc.student_id = s.student_id
WHERE m.score IN (SELECT score FROM science_marks) OR sc.score IN (SELECT score FROM mathematics_marks)

【讨论】:

  • 一个有用的练习是执行EXPLAIN EXTENDED [your query],然后执行SHOW WARNINGS,然后将原始查询与SQL引擎解析的查询进行比较。
  • 解释一下你的想法。
  • 当学生在数学和科学方面具有相同的score 值时会发生什么?学生是否与自己形成对称对?似乎这里的查询模式基本上会返回每个学生,作为与任何科学分数匹配的数学分数,以及与任何数学分数匹配的科学分数,而不考虑这些匹配分数是否来自同一个学生,形成一对..
【解决方案3】:

交叉加入所有学生,然后将每个学生的分数与其他学生进行比较。

select student1.student_name, student2.student_name
from (
         select s1.student_id, s1.student_name, m1.score "m_score", sc1.score "sc_score"
         from student s1
                  join mathematics_marks m1 on s1.student_id = m1.student_id
                  join science_marks sc1 on s1.student_id = sc1.student_id) student1,
     (
         select s2.student_id, s2.student_name, m2.score "m_score", sc2.score "sc_score"
         from student s2
                  join mathematics_marks m2 on s2.student_id = m2.student_id
                  join science_marks sc2 on s2.student_id = sc2.student_id) student2

where student1.student_id<>student2.student_id
  and student1.m_score = student2.sc_score
  and student1.sc_score = student2.m_score;

【讨论】:

  • 不要将连接操作的老式逗号语法与较新的 JOIN 关键字语法混用。
【解决方案4】:

对于这个要求,您需要对 2 个标记表进行多次连接,最后要获得需要两次连接学生表的学生的姓名:

select st1.student_name, st2.student_name
from mathematics_marks m1
inner join science_marks s1 on s1.student_id > m1.student_id and s1.score = m1.score
inner join mathematics_marks m2 on m2.student_id = s1.student_id 
inner join science_marks s2 on s2.student_id < m2.student_id and s2.score = m2.score
inner join student st1 on st1.student_id = m1.student_id
inner join student st2 on st2.student_id = m2.student_id;

请参阅demo

【讨论】:

    【解决方案5】:

    为简单起见并在单个表下获取所有分数,让我们创建一个视图。

    create view student_marks as select mm.student_id,mm.score as m_score, sm.score as s_score  
            from mathematics_marks mm
            inner join science_marks sm on mm.student_id=sm.student_id;
    

    现在我们在单个表格下拥有所有标记。 所以我们需要对上述视图进行自连接,找到满足对称条件的学生

    select distinct s.* 
    from student_marks sm1
    inner join student_marks sm2 on sm1.m_score=sm2.s_score and sm2.m_score=sm1.s_score
    left join student s on s.student_id = sm1.student_id or s.student_id=sm2.student_id;
    

    如果您不想创建视图,只需将student_marks 替换为视图查询即可。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多