我只是SQL的初学者,我遇到了无法解决的问题。
问题如下:
我有四张桌子Student: matrnr, name, semester, start_date
Listening: matrnr<Student>, vorlnr<Subject>
Subject: vorlnr, title, sws, teacher<Professor>
Professor: persnr, name, rank, room
我需要列出所有正在聆听某位教授主题的学生的名字。
编辑:
select s.*
from Student s, Listening h
where s.matrnr=h.matrnr
and h.vorlnr in (select v.vorlnr from Subject v, Professor p
where v.gelesenvon=p.persnr and p.name='Kant');
这就是我解决它的方法,但我不确定它是否是最佳解决方案。
答案 0 :(得分:3)
你的方法很好。只是,你想向学生展示,但是让学生加入列表,从而获得学生列表组合。
此外,您使用过时的连接语法。二十多年前它被明确的连接(INNER JOIN,CROSS JOIN等)取代了。
您只能使用子查询来执行此操作:
select *
from Students,
where matrnr in
(
select matrnr
from Listening
where vorlnr in
(
select vorlnr
from Subject
where gelesenvon in
(
select persnr
from Professor
where name='Kant'
)
)
);
或加入其他表:
select *
from Students
where matrnr in
(
select l.matrnr
from Listening l
inner join Subject s on s.vorlnr = l.vorlnr
inner join Professor p on p.persnr = s.gelesenvon and p.name='Kant'
);
或者使用EXISTS:
select *
from Students s
where exists
(
select *
from Listening l
inner join Subject su on su.vorlnr = l.vorlnr
inner join Professor p on p.persnr = su.gelesenvon and p.name='Kant'
where l.matrnr = s.matrnr
);
有些人喜欢加入everthing,然后使用DISTINCT进行清理。这很容易编写,特别是因为您不必首先考虑您的查询。但出于同样的原因,当涉及更多表格和更多逻辑时(如聚合),它会变得复杂,并且它也会变得非常难以阅读。
select distinct s.*
from Students s
inner join Listening l on l.matrnr = s.matrnr
inner join Subject su on su.vorlnr = l.vorlnr
inner join Professor p on p.persnr = su.gelesenvon and p.name='Kant';
最后这是一个品味问题。
答案 1 :(得分:3)
当您遇到SQL问题时,提出问题的一种好方法是将表格显示为CREATE TABLE
语句。此类语句显示详细信息,例如列的类型以及哪些列是主键。此外,这使我们能够实际构建一个小型数据库,以便重现错误行为或仅测试我们的解决方案。
CREATE TABLE Student
(
matrnr NUMBER(9) PRIMARY KEY,
name NVARCHAR2(50),
semester NUMBER(2),
start_date DATE
);
CREATE TABLE Listening
(
matrnr NUMBER(9), -- Student
vorlnr NUMBER(9), -- Subject
CONSTRAINT PK_Listening PRIMARY KEY (matrnr, vorlnr)
);
CREATE TABLE Subject
(
vorlnr NUMBER(9) PRIMARY KEY,
title NVARCHAR2(50),
sws NVARCHAR2(50),
teacher NUMBER(9) -- Professor
);
CREATE TABLE Professor
(
persnr NUMBER(9) PRIMARY KEY,
name NVARCHAR2(50),
rank NUMBER(3),
room NVARCHAR2(50)
);
使用此架构,我的解决方案如下所示:
SELECT *
FROM
Student
WHERE
matrnr IN (
SELECT L.matrnr
FROM
Listening L
INNER JOIN Subject S
ON L.vorlnr = S.vorlnr
INNER JOIN Professor P
ON S.teacher = P.persnr
WHERE P.name = 'Kant'
);
你可以在这里找到它:http://sqlfiddle.com/#!4/5179dc/2
由于我没有插入任何记录,因此它唯一测试的是语法和正确使用表名和列名。
您的解决方案不是最理想的。它不区分表的连接和指定为where子句的附加条件。如果他们参加教授的几门课程,它可以为每个学生产生几个结果记录。因此,我的解决方案将所有其他表放入子选择。
答案 2 :(得分:2)
select st.name
from student st
join listening l on l.matrnr = st.matrnr
join subject su on su.vorlnr = l.vorlnr
join professor p on su.teacher = p.persnr
where p.name = 'some name'
答案 3 :(得分:1)
SELECT *
FROM student
INNER JOIN listening ON student.matrnr = listening.matrnr
INNER JOIN subject ON listening.vorlnr = subject.vorlnr
INNER JOIN professor ON subject.teacher = professor.name
WHERE professor.name = 'some name'