我有这个代码及其临时表,因此您可以运行它。
create table #student(
id int identity(1,1),
name varchar(50)
)
create table #quiz(
id int identity(1,1),
name varchar(50),
points_worth int
)
create table #exam(
id int identity(1,1),
sequence int,
question varchar(50),
answer varchar(50),
quiz_id int
)
create table #student_taken(
id int identity(1,1),
sequence int,
answer varchar(50),
student_id int,
quiz_id int
)
insert into #student(name)
values('Uzumaki Naruto'),('Uchiha Sasuke'),('Haruno Sakura')
insert into #quiz(name,points_worth)
values('Chunin Exam',2)
insert into #exam(sequence,question,answer,quiz_id)
values(1,'Hinata and Neji are siblings','True',1),
(2,'Uchiha Sasuke is part of the Akatsuki','False',1),
(3,'Tsunade and Jiraiya has a son','False',1)
insert into #student_taken(sequence,answer,quiz_id,student_id)
values(1,'True',1,1),(2,'True',1,1),(3,'True',1,1),(1,'True',1,2),(2,'False',1,2),(3,'False',1,2),
(1,'True',1,3),(2,'False',1,3),(3,'False',1,3)
drop table #student
drop table #exam
drop table #quiz
drop table #student_taken
所以你可以看到我Uzumaki Naruto只有1分,因为他只有1个正确的答案,Sakura和Sasuke都有3分。
现在我希望它像这样:
id name score
1 Uzumaki Naruto 2
2 Uchiha Sasuke 6
3 Haruno Sakura 6
他得到了6,因为在我的#quiz表中我添加了值(这是每个项目的价值)。
所以现在我想知道是否需要group by子句呢?什么是正确的求和,我希望如果True = True则加1点,False = False,False = True不计算。
这是我的尝试
select
ST.student_id,
SUM(1 * Q.points_worth) 'sum'
from #student_taken ST
inner join #exam E
on E.quiz_id = ST.quiz_id
inner join #quiz Q
on Q.id = E.quiz_id
group by ST.student_id
答案 0 :(得分:9)
我不确定你的问题在这里。 @JorgeCampos不太正确,因为只有在同一数据集中返回加重和非聚合字段时才需要GROUP BY
(不使用OVER
子句)。
至于获得结果集,我不太确定你是如何得出结论的。 points_worth的值在你的测验表中,而不是考试表中,所以我假设每个问题的测验值都相同?如果是这样,这是您的查询的一个想法:
SELECT q.[name] AS QuizName,
s.[name] As StudentName,
COUNT(CASE WHEN st.answer = e.answer THEN 1 END) * q.points_worth AS Score,
COUNT(CASE WHEN st.answer = e.answer THEN 1 END) AS Correct,
COUNT(CASE WHEN st.answer != e.answer THEN 1 END) AS Incorrect
FROM #student s
JOIN #student_taken st ON s.id = st.student_id
JOIN #exam e ON st.[sequence] = e.id
JOIN #quiz q ON e.quiz_id = q.id
GROUP BY q.[name], s.[name],
q.points_worth;
然而,我们可以进一步看看学生是否真的回答了所有问题(并排除那些没有回答的问题),因此我们得到:
INSERT INTO #quiz([name],points_worth)
VALUES('Basic Maths',1);
INSERT INTO #exam([sequence],question,answer,quiz_id)
VALUES(1,'5 + 2 * 3 = 21','False',2),
(2,'9 - 1 * 2 = 7','True',2);
INSERT INTO #student ([name])
VALUES ('Jane Smith'),('Sally Bloggs');
INSERT INTO #student_taken ([sequence],answer,quiz_id,student_id)
VALUES (1, 'false', 1, 4),
(1, 'false', 2, 4),
(2, 'true', 2, 4),
(1, 'true', 2, 5);
GO
SELECT q.[name] AS QuizName,
s.[name] As StudentName,
COUNT(CASE WHEN st.answer = e.answer THEN 1 END) * q.points_worth AS Score,
COUNT(CASE WHEN st.answer = e.answer THEN 1 END) AS Correct,
COUNT(CASE WHEN st.answer != e.answer THEN 1 END) AS Incorrect,
COUNT(CASE WHEN st.answer IS NULL THEN 1 END) AS Unanswered
FROM #quiz q
JOIN #exam e ON q.id = e.quiz_id
CROSS JOIN #student s
LEFT JOIN #student_taken st ON s.id = st.student_id
AND e.[sequence] = st.[sequence]
AND q.id = st.quiz_id
WHERE EXISTS (SELECT 1 FROM #student_taken sq WHERE sq.student_id = s.id AND sq.quiz_id = q.id)
GROUP BY q.[name], s.[name],
q.points_worth;
希望有所帮助。
答案 1 :(得分:2)
在sum
内添加条件。我还注意到从#student_taken
到#exam
的加入并未正常工作,因为您&#39 ;只需加入quiz_id
,您还需要加入sequence
。
所以,您尝试进行这些修改:
select
ST.student_id,
SUM(IIF(ST.answer = E.answer, Q.points_worth, 0)) 'sum'
from #student_taken ST
inner join #exam E
on E.quiz_id = ST.quiz_id and ST.sequence = E.sequence
inner join #quiz Q
on Q.id = st.quiz_id
group by ST.student_id
IIF
函数将第一个参数计算为条件,如果为true则返回第二个参数,如果为false则返回第三个参数。因此,如果学生回答了考试期望的内容(ST.answer = E.answer
),则会返回值,否则为0。
如果您不想使用IIF
,则可以使用案例陈述:case when ST.answer = E.answer then Q.points_worth else 0 end
。我个人认为IIF
看起来更干净,如果你弄乱一个案例陈述,SQL Server Management Studio会因为语法提示而有些疯狂。
答案 2 :(得分:2)
你可以试试这个方法:找出多少正确的分数/学生(在CTE内部查询),然后取结果并加入#quiz
表,通过应用points_worth
来计算最终分数
;with cte as (
select
st.student_id
,st.quiz_id
,COUNT(e.id) as points
from #student_taken st
left join #exam e
on st.quiz_id = e.quiz_id
and st.answer = e.answer
and st.sequence = e.sequence
group by st.student_id, st.quiz_id
) select
student_id
,s.name
--,quiz_id
,points * q.points_worth
from cte
inner join #quiz q
on quiz_id = q.id
inner join #student s
on student_id = s.id