SQL Server似乎不正确



我有一个存储课程成绩的表。一门课程可以有多个考试,每个考试都有自己的权重。

在这个例子中,我有一个学生的两个考试分数,然后将其加权得到课程分数。标记和权重都存储在FLOAT列中。

下面是我提取考试分数的代码:

WITH RawData AS 
(
SELECT 
lngRelatedScoreID AS [ID],
cc.strName AS Exam,
cc.dblWeighting, 
sci.dblModeratedComponentScorePercent AS Mark
FROM 
tblStudentComponentInformation sci 
INNER JOIN 
tblCourseComponents cc ON sci.lngExamID = cc.lngExamID
WHERE 
sci.lngRelatedScoreID IN (73652)
)
SELECT * FROM RawData

结果如下:

ID73652飞行动力学与控制考试0.750.90573652飞行动力学与控制课程0.250.92

正如在评论中提到的,"问题"是数据类型,而不是表达式。

如果我们看下面的例子:

SELECT [ID],
SUM(FloatWeighting*FloatMark) AS Float,
SUM(Decimalweighting*DecimalMark) AS Decimal,
CONVERT(decimal(18,12),SUM(FloatWeighting*FloatMark)) AS ConvertedFloat,
ROUND(SUM(FloatWeighting*FloatMark),4) AS RoundedFloat,
ROUND(SUM(Decimalweighting*DecimalMark),4) AS RoundedDecimal
FROM (VALUES(73652,'Flight Dynamics and Control Exam      ',CONVERT(float,0.75),CONVERT(decimal(3,2),0.75),CONVERT(float,0.905),CONVERT(decimal(4,3),0.905)),
(73652,'Flight Dynamics and Control Coursework',CONVERT(float,0.25),CONVERT(decimal(3,2),0.25),CONVERT(float,0.92),CONVERT(decimal(4,3),0.92)))V(ID,Exam,FloatWeighting,DecimalWeighting,FloatMark,DecimalMark)
GROUP BY ID;

如果运行此命令,将得到以下结果:

ID    Float   Decimal ConvertedFloat RoundedFloat RoundedDecimal
----- ------- ------- -------------- ------------ --------------
73652 0.90875 0.90875 0.908750000000 0.9088       0.90880

注意,四舍五入的decimal值提供了您期望的值,但四舍五入的float没有。这是因为,正如在评论中讨论的那样,浮点值不是基数为10的值,而是基数为2的值。因此float0.90875实际上不是0.90875,而是0.908749999999999946709294817992486059665679931640625。注意,这个值实际上(只是)小于0.90875

因此,当您应用函数ROUND时,使用上面的值,当您将该值ROUND到小数点后4位时,0.9087正确答案。

因此,这里真正的解决方案是修复您的设计和表的ALTER,使列成为decimal。例如,它可能是:
ALTER TABLE dbo.tblCourseComponents ALTER COLUMN Mark decimal(4,3);
请注意,您需要为实际值使用适当的比例和精度。

如果你不能改变数据类型,或者至少现在不能,那么你可以先显式地将值转换为decimal,然后再进行算术运算。例如:

ROUND(SUM(CONVERT(decimal(3,2),Weighting)*CONVERT(decimal(4,3),Mark)),4)

同样,请确保您使用适当的精度和比例为您的数据。

相关内容

  • 没有找到相关文章