gpt4 book ai didi

SQL Server 似乎四舍五入不正确

转载 作者:行者123 更新时间:2023-12-04 17:13:24 25 4
gpt4 key购买 nike

我有一个表格来存储类(class)结果。一门类(class)可能有多个考试,每个考试都有自己的权重。
在这个例子中,我有一个学生的 2 个考试分数,然后加权得出类(class)分数。标记和权重都存储在 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
结果显示如下:


ID
考试
权重
标记


73652
飞行动力学和控制考试
0.75
0.905

73652
飞行动力学和控制类(class)
0.25
0.92


我现在合并两行,将权重乘以标记:
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
[ID],
SUM(Mark * dblWeighting) AS TotalWeightedMark
FROM
RawData
GROUP BY
[ID]
返回以下内容 - 正如预期的那样:


ID
总加权标记


73652
0.90875


但是,我希望结果保留 4 位小数,因此当我将标记乘以四舍五入并对结果求和时,我添加了 ROUND功能:
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
[ID],
ROUND(SUM(Mark * dblWeighting), 4) AS TotalWeightedMark
FROM
RawData
GROUP BY
[ID]
这是我得到的:


ID
总加权标记


73652
0.9087


我的问题是为什么这似乎是截断而不是四舍五入,因为我没有为 ROUND 的最后一个参数指定默认值以外的任何值。功能。
我想知道是不是因为使用 FLOAT而不是 DECIMAL对于列,但在这种情况下,计算中不需要任何四舍五入,除了我指定从 5 位四舍五入的一个计算。
任何人都可以建议吗?
如果相关,我使用的是 SQL Server 2017。
谢谢。

最佳答案

正如评论中提到的,“问题”是数据类型,而不是表达式。
如果我们以下面的例子为例:

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 value 提供您期望的值,但四舍五入的 float才不是。这是因为,正如评论中所讨论的,浮点值不是基数为 10 的值,而是基数为 2 的值。结果 float值(value) 0.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)
再次确保您对数据使用适当的精度和比例。

关于SQL Server 似乎四舍五入不正确,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69073606/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com