我正在尝试一些 SQL 练习题,但我在回答一个问题时遇到了麻烦。
问题希望我返回一个包含[测试 ID、测试名称和测试难度] 的表。问题是我必须根据两个表之间的数据创建 [测试难度] 列(参与者分数在表 A 中,测试名称在表 B 中)。这些表共享测试 ID。
简而言之,我需要连接两个表,然后平均分数,然后创建新的测试难度列并根据平均分数填充它(例如,如果平均分数小于 20,则测试难度 =“hard” ).
目前,我已成功连接表格并计算平均分数,但我在创建此新列并根据条件填充的最后部分遇到了麻烦。有人可以帮忙吗?
注意,创建新表不是一个选项,所有操作都应该通过查询执行区完成。
代码如下:
表A
create table reports ( id integer not null, task_id integer not null, candidate varchar(40) not null, score integer not null, unique(id) );
表B
create table tasks ( id integer not null, name varchar(40) not null, unique(id) )
各表中的值
insert into reports values (13, 101, 'John Smith', 100);
insert into reports values (24, 123, 'Delaney Lloyd', 34);
insert into reports values (37, 300, 'Monroe Jimenez', 50);
insert into reports values (49, 101, 'Stanley Price', 45);
insert into reports values (51, 142, 'Tanner Sears', 37);
insert into reports values (68, 142, 'Lara Fraser', 3);
insert into reports values (83, 300, 'Tanner Sears', 0);
insert into tasks values (101, 'MinDist');
insert into tasks values (123, 'Equi');
insert into tasks values (142, 'Median');
insert into tasks values (300, 'Tricoloring');
我的代码:
select *
from
(
select reports.task_id,
tasks.name,
avg(reports.score) as average
from reports
join tasks
on tasks.id = reports.task_id
group by reports.task_id, tasks.name
) practice;
一种选择(不是唯一的选择)是将现有查询放入公共表表达式中,并将其连接到更新语句。它看起来像:
alter table tasks add column "Test Difficulty" varchar(40);
with cte as
(select reports.task_id,
tasks.name,
avg(reports.score) as average
from reports
join tasks
on tasks.id = reports.task_id
group by reports.task_id, tasks.name)
update tasks
set "Test Difficulty" =
CASE
WHEN cte.average <= 20.0 THEN 'Hard'
WHEN cte.average <= 40.0 THEN 'Medium'
ELSE 'Easy'
END
from cte
WHERE cte.task_id = tasks.id
您可以看到它在这里工作。
with cte as (...)
只是包装您现有的查询。 update tasks set ... from cte where cte.task_id = tasks.id
将您的查询连接到您要更新的表。
case
语句决定您要填充的文本。因为您没有完全指定要求,所以我编造了一些数字/文本,但基本思想应该适用于您的实际问题。
另一种选择可能涉及在子查询中进行计算。 类似这样的事情。
有点不清楚您是否想将结果插入到某个地方,但这里有一些与您可以获得的查询尽可能接近的内容:
select
practice.*,
case
when practice.average <= 20 then 'HARD'
when practice.average > 20 and practice.average <= 40 then 'MEDIUM'
else 'EASY'
end as test_difficulty
from (
select
reports.task_id,
tasks.name,
avg(reports.score) as average
from reports
join tasks on tasks.id = reports.task_id
group by reports.task_id, tasks.name
) practice;
当然,您可以根据需要更改 CASE 语句。我正在使用“practice.average > 20 和practice.average <= 40" instead of BETWEEN, because BETWEEN is inclusive; this way each difficulty starts on .0(...)01 and ends on 0.
当然还有很多其他方法可以做到这一点 - CTE、函数等 - 但这似乎最接近您所描述的。