我对postgresql很新。任何专家都可以帮我解决这个问题。
考虑为大学系统录制创建的以下PostgreSQL表,学生可以使用哪些模块:
CREATE TABLE module (id bigserial, name text);
CREATE TABLE student (id bigserial, name text);
CREATE TABLE takes (student_id bigint, module bigint);
重写SQL以包含合理的主键。
CREATE TABLE module
(
m_id bigserial,
name text,
CONSTRAINT m_key PRIMARY KEY (m_id)
);
CREATE TABLE student
(
s_id bigserial,
name text
CONSTRAINT s_key PRIMARY KEY (s_id)
);
CREATE TABLE takes
(
student_id bigint,
module bigint,
CONSTRAINT t_key PRIMARY KEY (student_id)
);
鉴于此架构,我有以下问题:
编写一个SQL查询来计算有多少学生正在使用DATABASE。
SELECT COUNT(name)
FROM student
WHERE module = 'DATABASE' AND student_id=s_id
编写一个SQL查询,以显示所有学生参加数据库的学生ID和姓名(但没有别的)
SELECT s_id, name
FROM Student, take
WHERE module = 'DATABASE' AND student_id = s_id
编写SQL查询以显示未参加数据库的所有学生的学生ID和姓名(但没有其他内容)。
SELECT s_id, name
FROM Student, take
WHERE student_id = s_id AND module != 'DATABASE'
以上是我的答案。如果我错了请纠正我,请评论原因。感谢您的专业知识。
答案 0 :(得分:1)
这看起来像是家庭作业,所以我不打算给出详细的答案。一些提示:
我发现了一个使用´
引号而不是'
撇号的情况。这表明你正在用类似Microsoft Word编写SQL,这就是所谓的“智能引号”。不要这样做。使用合理的文本编辑器。如果你在Windows上,Notepad ++是一个受欢迎的选择。(修正了它在重新格式化问题时,但想提一下。)
不要使用旧的非ANSI连接语法JOIN table1, table2, table3 WHERE ...
。阅读起来很可怕,犯错误要容易得多。你应该从来没有被教过。此外,对您的专栏进行限定 - take.module
不仅仅是module
。总是写ANSI连接,例如在上面的示例中:
FROM Student, take
WHERE module = 'DATABASE' AND student_id = s_id
变为
FROM student
INNER JOIN take
ON take.module = 'DATABASE'
AND take.student_id = student.s_id;
(如果表名很长,您可以使用别名,例如FROM student s
,然后s.s_id
)
查询3完全错误。想象一下,如果take
有两行学生,一个学生正在学习database
,另一行学习cooking
。您的查询仍会返回结果,即使他们正在使用database
。 (它也会多次返回相同的学生ID,这是您不想要的)。想想subqueries。您需要使用student
过滤未参加NOT EXISTS (SELECT .... FROM take ...)
的学生来查询database
表格。其余的你可以自己弄清楚。
此外,您的架构实际上并未强制执行约束,即学生一次只能DATABASE
一次。要么添加,要么在您的查询中考虑学生可能会在DATABASE
两次注册。