根据其他表中的数据更新和更新数据
Update and renew data based on data in other tables
有3个tablestudent
、course
、takes
如下
CREATE TABLE student
(
ID varchar(5),
name varchar(20) NOT NULL,
dept_name varchar(20),
tot_cred numeric(3,0) CHECK (tot_cred >= 0),
PRIMARY KEY (ID),
FOREIGN KEY (dept_name) REFERENCES department
ON DELETE SET NULL
)
CREATE TABLE takes
(
ID varchar(5),
course_id varchar(8),
sec_id varchar(8),
semester varchar(6),
year numeric(4,0),
grade varchar(2),
PRIMARY KEY (ID, course_id, sec_id, semester, year),
FOREIGN KEY (course_id, sec_id, semester, year) REFERENCES section
ON DELETE CASCADE,
FOREIGN KEY (ID) REFERENCES student
ON DELETE CASCADE
)
CREATE TABLE course
(
course_id varchar(8),
title varchar(50),
dept_name varchar(20),
credits numeric(2,0) CHECK (credits > 0),
PRIMARY KEY (course_id),
FOREIGN KEY (dept_name) REFERENCES department
ON DELETE SET NULL
)
tot_cred
student
table 列数据现在被分配了随机值(不正确),我想执行更新和更新这些数据的查询基于课程的 grade
每个学生都已经上过。对于那些获得 F
成绩的学生将被排除在外,而那些没有参加任何课程的学生将被分配为 0 作为 tot_cred
。
我想到了两种方法,一种是
UPDATE student
SET tot_cred = (SELECT SUM(credits)
FROM takes, course
WHERE takes.course_id = course.course_id
AND student.ID = takes.ID
AND takes.grade <> 'F'
AND takes.grade IS NOT NULL)
这个查询满足了我的所有需求,但是对于那些没有参加任何课程的学生,它确实分配了 NULL 值而不是 0。
第二种是使用case when
UPDATE student
SET tot_cred = (select sum(credits)
case
when sum(credits) IS NOT NULL then sum(credits)
else 0 end
FROM takes as t, course as c
WHERE t.course_id = c.course_id
AND t.grade<>'F' and t.grade IS NOT NULL
)
但是它给所有学生分配了 0。有什么办法可以达到上面的要求吗?
如果第一个查询满足您的要求,唯一的问题是它 returns NULL
对于没有参加任何课程的学生,那么最简单的解决方案是使用而不是 SUM()
聚合函数函数 TOTAL()
将 return 0
而不是 NULL
:
UPDATE student AS s
SET tot_cred = (
SELECT TOTAL(c.credits)
FROM takes t INNER JOIN course c
ON t.course_id = c.course_id
WHERE t.ID = s.ID AND t.grade <> 'F' AND t.grade IS NOT NULL
);
同样可以用 COALESCE()
:
SELECT COALESCE(SUM(credits), 0)...
此外,使用带有 ON
子句的适当联接和表的别名以提高可读性。
有3个tablestudent
、course
、takes
如下
CREATE TABLE student
(
ID varchar(5),
name varchar(20) NOT NULL,
dept_name varchar(20),
tot_cred numeric(3,0) CHECK (tot_cred >= 0),
PRIMARY KEY (ID),
FOREIGN KEY (dept_name) REFERENCES department
ON DELETE SET NULL
)
CREATE TABLE takes
(
ID varchar(5),
course_id varchar(8),
sec_id varchar(8),
semester varchar(6),
year numeric(4,0),
grade varchar(2),
PRIMARY KEY (ID, course_id, sec_id, semester, year),
FOREIGN KEY (course_id, sec_id, semester, year) REFERENCES section
ON DELETE CASCADE,
FOREIGN KEY (ID) REFERENCES student
ON DELETE CASCADE
)
CREATE TABLE course
(
course_id varchar(8),
title varchar(50),
dept_name varchar(20),
credits numeric(2,0) CHECK (credits > 0),
PRIMARY KEY (course_id),
FOREIGN KEY (dept_name) REFERENCES department
ON DELETE SET NULL
)
tot_cred
student
table 列数据现在被分配了随机值(不正确),我想执行更新和更新这些数据的查询基于课程的 grade
每个学生都已经上过。对于那些获得 F
成绩的学生将被排除在外,而那些没有参加任何课程的学生将被分配为 0 作为 tot_cred
。
我想到了两种方法,一种是
UPDATE student
SET tot_cred = (SELECT SUM(credits)
FROM takes, course
WHERE takes.course_id = course.course_id
AND student.ID = takes.ID
AND takes.grade <> 'F'
AND takes.grade IS NOT NULL)
这个查询满足了我的所有需求,但是对于那些没有参加任何课程的学生,它确实分配了 NULL 值而不是 0。
第二种是使用case when
UPDATE student
SET tot_cred = (select sum(credits)
case
when sum(credits) IS NOT NULL then sum(credits)
else 0 end
FROM takes as t, course as c
WHERE t.course_id = c.course_id
AND t.grade<>'F' and t.grade IS NOT NULL
)
但是它给所有学生分配了 0。有什么办法可以达到上面的要求吗?
如果第一个查询满足您的要求,唯一的问题是它 returns NULL
对于没有参加任何课程的学生,那么最简单的解决方案是使用而不是 SUM()
聚合函数函数 TOTAL()
将 return 0
而不是 NULL
:
UPDATE student AS s
SET tot_cred = (
SELECT TOTAL(c.credits)
FROM takes t INNER JOIN course c
ON t.course_id = c.course_id
WHERE t.ID = s.ID AND t.grade <> 'F' AND t.grade IS NOT NULL
);
同样可以用 COALESCE()
:
SELECT COALESCE(SUM(credits), 0)...
此外,使用带有 ON
子句的适当联接和表的别名以提高可读性。