我试图让这个陈述发挥作用。但我无法弄清楚。
- 列出从未参加过数据库课程的学生的姓名。
醇>
我有这个:
select distinct s1.name, e1.section_id
from students s1
inner join enrollment e1 on e1.student_id = s1.id
where e1.course_id != 12
但这并没有删除那个参加该部分的学生,所以我被卡住了。
数据库看起来像(我很抱歉,我不知道如何将数据库插入此处)
table students (
id integer primary key,
name varchar(255),
graduation_date date,
major_id integer references departments(id)
);
insert into students (id, name, graduation_date, major_id) values
(1, 'Joe', null, 10);
insert into students (id, name, graduation_date, major_id) values
(2, 'Amy', '2009-04-22', 20);
insert into students (id, name, graduation_date, major_id) values
(3, 'Max', null, 10);
create table courses (
id integer primary key,
title varchar(255),
units integer,
department_id integer references departments(id)
);
insert into courses (id, title, units, department_id) values
(12, 'Databases', 4, 10);
insert into courses (id, title, units, department_id) values
(22, 'Compilers', 4, 10);
insert into courses (id, title, units, department_id) values
(32, 'Calculus 1', 4, 20);
create table sections (
id integer primary key,
course_id integer not null references courses(id),
instructor_id integer references faculty(id),
year integer
);
insert into sections (id, course_id, instructor_id, year) values
(12, 12, 6, 2007);
insert into sections (id, course_id, instructor_id, year) values
(13, 12, 1, 2008);
insert into sections (id, course_id, instructor_id, year) values
(14, 22, 1, 2008);
insert into sections (id, course_id, instructor_id, year) values
(23, 12, 6, 2009);
create table enrollment (
id integer primary key,
student_id integer not null references students(id),
section_id integer not null references sections(id),
grade_id integer references grades(id)
);
insert into enrollment (id, student_id, section_id, grade_id) values
(14, 1, 12, 8);
insert into enrollment (id, student_id, section_id, grade_id) values
(15, 1, 13, 3);
insert into enrollment (id, student_id, section_id, grade_id) values
(16, 1, 14, 5);
insert into enrollment (id, student_id, section_id, grade_id) values
(17, 1, 32, 1);
insert into enrollment (id, student_id, section_id, grade_id) values
(18, 1, 34, 2);
insert into enrollment (id, student_id, section_id, grade_id) values
(19, 1, 53, 13);
insert into enrollment (id, student_id, section_id, grade_id) values
(24, 3, 12, 2);
insert into enrollment (id, student_id, section_id, grade_id) values
(25, 3, 14, 5);
insert into enrollment (id, student_id, section_id, grade_id) values
(26, 3, 32, 1);
insert into enrollment (id, student_id, section_id, grade_id) values
(27, 3, 34, 2);
insert into enrollment (id, student_id, section_id, grade_id) values
(28, 3, 54, 7);
insert into enrollment (id, student_id, section_id, grade_id) values
(34, 2, 43, 3);
insert into enrollment (id, student_id, section_id, grade_id) values
答案 0 :(得分:2)
不,不要加入所有内容,然后尝试使用DISTINCT
进行清理。这是一个糟糕的方法。而是先考虑一下你想要选择的内容。然后逐步编写查询。
“从未上过课程数据库的学生”是
我突出了所需的关键字。所以你有三个选择:
EXCEPT
NOT IN
NOT EXISTS
如果您还有其他问题,请尝试这些并返回此处。
更新:现在你解决了它(甚至接受了我的回答:-),这里有一些编写查询的方法:
使用IN子句进行查询:
select name
from students
where id not in
(
select student_id
from enrollment
where section_id in
(
select id
from sections
where course_id = (select id from courses where title = 'Databases')
)
);
使用EXISTS子句查询:
select name
from students
where not exists
(
select *
from enrollment
where section_id in
(
select id
from sections
where course_id = (select id from courses where title = 'Databases')
)
and student_id = students.id
);
使用EXCEPT进行查询(这里的解决方案不是很好,因为它会两次查询学生表,但有时候EXCEPT是解决问题的直接方法)。我在这里使用子查询而不是WHERE students.id IN (...)
,只是为了展示技术。
select name
from students
join
(
select id
from students
except
select student_id
from enrollment
where section_id in
(
select id
from sections
where course_id = (select id from courses where title = 'Databases')
)
) found_students on found_students.id = students.id;
使用COUNT和HAVING查询,看起来非常紧凑。然而,它更容易出错。有一点不是混淆外连接中的ON和WHERE,另一种是计算正确的列。我们必须确保计算一个不可为空的表格部分字段,因此我们确信学生的所有注册都不符合实际的数据库部分。
select s.id, s.name
from students s
left join enrollment e on e.student_id = s.id
left join sections s on s.id = e.section_id
and s.course_id = (select id from courses where title = 'Databases')
group by s.id, s.name
having count(s.id) = 0;
答案 1 :(得分:1)
我认为上面的查询使主题变得复杂,所以我添加了自己的。
SELECT s.*
FROM students s
LEFT JOIN (enrollment e
INNER JOIN sections se
ON se.id = e.section_id
INNER JOIN courses c
ON c.id = se.course_id AND c.title = 'Databases')
ON s.id = e.student_id
WHERE
e.id IS NULL