SQL学生标记功能查询

Mav*_*ugu 2 sql database

在亚马逊上作为面试问题来测试基本的SQL技能,我有点失败了。请考虑以下表格:

Student - Stid, Stname, Details
Subject - Subid, Subname
Marks - Stid, Subid, mark
Run Code Online (Sandbox Code Playgroud)

编写查询以打印在每个学科中得分最高的学生的姓名列表。

我给的错误答案是:

select A.Stname from A as Student, B as 
(select Stid, Subid, max(mark) from Marks groupby Subid) where A.Stid = B.Stid
Run Code Online (Sandbox Code Playgroud)

我以为您可以拥有一个表B,您可以在其中单独获得最高分并将其与学生表A中的名称匹配。但是事实证明,我的“ groupby”是错误的。

我认为可以提出的另一个问题是,如果一个科目中得分最高的学生多于一个,甚至应包括他们的名字。

您能帮忙解决这些疑问吗?它们似乎很简单,但我无法理解。

谢谢!

Mic*_*uen 5

您只需要将问题分成几步,然后一步一步地解决即可

首先,获得每个学科的最高分数:

select SubjectID, max(MarkRate)
from Mark
group by SubjectID;
Run Code Online (Sandbox Code Playgroud)

然后查询谁具有最大MarkRate的SubjectID:

select SubjectID, MarkRate, StudentID
from Mark
where (SubjectID,MarkRate)
in
  (
  select SubjectID, max(MarkRate)
  from Mark
  group by SubjectID
  )
order by SubjectID, StudentID;
Run Code Online (Sandbox Code Playgroud)

然后获取学生的姓名,而不是仅显示StudentID:

select SubjectName, MarkRate, StudentName
from Mark
join Student using(StudentID)
join Subject using(SubjectID)
where (SubjectID,MarkRate)
in
  (
  select SubjectID, max(MarkRate)
  from Mark
  group by SubjectID
  )
order by SubjectName, StudentName
Run Code Online (Sandbox Code Playgroud)

除了在连接和关联结果方面,数据库供应商的人为差异外,基本步骤是相同的​​。首先,将问题分成几小部分,然后在解决每个问题时将其集成,因此不会造成混乱。


样本数据:

CREATE TABLE Student
    (StudentID int, StudentName varchar(6), Details varchar(1));    
INSERT INTO Student
    (StudentID, StudentName, Details)
VALUES
    (1, 'John', 'X'),
    (2, 'Paul', 'X'),
    (3, 'George', 'X'),
    (4, 'Paul', 'X');

CREATE TABLE Subject
    (SubjectID varchar(1), SubjectName varchar(7));    
INSERT INTO Subject
    (SubjectID, SubjectName)
VALUES
    ('M', 'Math'),
    ('E', 'English'),
    ('H', 'History');

CREATE TABLE Mark
    (StudentID int, SubjectID varchar(1), MarkRate int);    
INSERT INTO Mark
    (StudentID, SubjectID, MarkRate)
VALUES
    (1, 'M', 90),
    (1, 'E', 100),
    (2, 'M', 95),
    (2, 'E', 70),
    (3, 'E', 95),
    (3, 'H', 98),
    (4, 'H', 90),
    (4, 'E', 100);
Run Code Online (Sandbox Code Playgroud)

此处进行实时测试:http : //www.sqlfiddle.com/#!1/08728/3


IN元组测试仍然是任何其他名称的联接:

转换这个..

select SubjectName, MarkRate, StudentName
from Mark
join Student using(StudentID)
join Subject using(SubjectID)

where (SubjectID,MarkRate)
in
  (
  select SubjectID, max(MarkRate)
  from Mark
  group by SubjectID
  )

order by SubjectName, StudentName
Run Code Online (Sandbox Code Playgroud)

..加入:

select SubjectName, MarkRate, StudentName
from Mark
join Student using(StudentID)
join Subject using(SubjectID)

join
  (
  select SubjectID, max(MarkRate) as MarkRate
  from Mark
  group by SubjectID
  ) as x using(SubjectID,MarkRate)

order by SubjectName, StudentName
Run Code Online (Sandbox Code Playgroud)

将此代码与立即执行的代码进行对比。看看独立查询上的JOIN看起来像IN结构吗?它们看起来几乎一样,只是用JOIN关键字代替了IN;并且用JOIN替换的IN关键字实际上更长,您需要为独立查询的列result(max(MarkRate) AS MarkRate)和子查询本身(as x)加上别名。无论如何,这只是样式问题,我更倾向于使用IN子句,因为其意图更加清晰。仅使用JOIN来反映数据关系。

无论如何,这是适用于所有不支持元组test(IN)的数据库的查询:

select sb.SubjectName, m.MarkRate, st.StudentName
from Mark as m
join Student as st on st.StudentID = m.StudentID
join Subject as sb on sb.SubjectID = m.SubjectID

join
  (
  select SubjectID, max(MarkRate) as MaxMarkRate
  from Mark
  group by SubjectID
  ) as x on m.SubjectID = x.SubjectID AND m.MarkRate = x.MaxMarkRate

order by sb.SubjectName, st.StudentName
Run Code Online (Sandbox Code Playgroud)

实时测试:http//www.sqlfiddle.com/#!1/08728/4