在函数调用后合并返回错误值然后乘法
Coalesce returning wrong value after a function call followed by multiplication
我有一份提供信息的报告,但我得到的信息不一致,原因是 SQL 视图或视图中嵌套的 SQL 函数似乎存在问题。我已经尝试找到一种调试 SQL 视图的方法,但是,SSMS 似乎只会调试存储过程,所以我不太确定如何逐步执行并查看发生了什么。这真的让我难住了,我忍不住想知道这是否是一个舍入问题。
GetItemAverageCost RETURNS DECIMAL(12,2)
和 sitli.QuantityIssuedAtStockUOM 中的数据类型是 System.Int64 / bigint(旁注:我很困惑为什么 LINQPad 为该列显示 2 种数据类型。在左侧的树中,展开 sitli 后table 并将鼠标悬停在 QuantityIssuedAtStockUOM 上,气球 BigInt NOT NULL 会弹出,但是当我 Take(100) 并将鼠标悬停在结果集中的列上时,它会显示 System.Int64)。不管怎样,这是 COALESCE 函数。
COALESCE((dbo.GetItemAverageCost(ItemModel.IDItemModel)*sitli.QuantityIssuedAtStockUOM) / ISNULL(NULLIF(ItemModel.UOMFactor, 0),1),0) -- 259.73
--ROUND(COALESCE((dbo.GetItemAverageCost(ItemModel.IDItemModel)*sitli.QuantityIssuedAtStockUOM) / ISNULL(NULLIF(ItemModel.UOMFactor, 0),1),0),2) -- 259.73
--COALESCE(ROUND((dbo.GetItemAverageCost(ItemModel.IDItemModel)*sitli.QuantityIssuedAtStockUOM) / ISNULL(NULLIF(ItemModel.UOMFactor,2), 0),1),0) -- 259.70
--COALESCE((ROUND(dbo.GetItemAverageCost(ItemModel.IDItemModel),2)*sitli.QuantityIssuedAtStockUOM) / ISNULL(NULLIF(ItemModel.UOMFactor, 0),1),0) -- 259.73
原创/错误合并:
COALESCE(dbo.GetItemAverageCost(ItemModel.IDItemModel)*sitli.QuantityIssuedAtStockUOM,0)
我不确定还包括什么,但我没有在网上找到很多资源来深入了解这种情况。非常感谢您的宝贵时间。
编辑:GetItemAverageCost:
ALTER FUNCTION GetItemAverageCost
(
@IDItemModel varchar(8000)
)
RETURNS DECIMAL(16,4)
--RETURNS DECIMAL(12,2)
AS
BEGIN
RETURN
(
SELECT
COALESCE(AVG(poli.UnitPrice),0) as AvgCost
-- COALESCE(ROUND(AVG(poli.UnitPrice),0),2) as AvgCost 260.00
FROM ItemModel im
LEFT JOIN VendorItem vi
ON im.IDItemModel = vi.IDItemModel
JOIN POLineItem poli
ON vi.IDVendorItem = poli.IDVendorItem
WHERE
im.IDItemModel = @IDItemModel
GROUP BY
im.IDItemModel,
im.ItemNumber
)
END
修复;让你的函数 return 16,4 而不是 12,2 然后在乘以数量后舍入两位两位小数。
"When a given report is run, there are no errors thrown. But the calculations are off. For example a part number 12 shows a quantity of 24 were issued at a cost of 9.73. However, each part costs .82 so the calculation should be 9.68. I'm not sure where the difference of 5 cents is coming from. The 9.73 is the result of the COALESCE function above. Hopefully this makes sense"
运行 SQL 仅适用于独立于函数的第 12 部分,您会看到平均值为 10.822083333333333333333333333333(10.82 5/24ths)
- 24*单价 = 259.73 美元
- 单价 = 259.73/24
- 单价 = 10.82 美元 5/24。
您会看到差异为 $.05
- 10.82 5/24。 *24 = 259.73
- 10.82 * 24 = 259.68
5 美分的差异并没有平均分配到剩余的 24 美分中。因此在使用您的函数时出现舍入误差。
当你想到去商店买东西时,它总是等于一分钱。当你去加油站时,他们会收取最接近的 .00001 美分。 (或者在你的情况下是 4 位小数)
直到乘以数量或实际现金需要易手时,才进行四舍五入。如果做得太早,你会看到你看到的舍入错误。
因此,您消除了 over/under 收费舍入错误,最多您会比您应该少收或多收一分钱。
好的,非常感谢一路上提供帮助的所有人。有几个问题阻止我得到正确的答案。一方面,我大部分时间都在使用不正确的表达方式。其次,在我弄清楚要使用哪个表达式之后,接下来就是将 ROUND 函数放在正确的位置。
所以,我应该用来计算平均成本的表达式是:
COALESCE(dbo.GetItemAverageCost(Item.IDItemModel) / ISNULL(NULLIF(UOMFactor, 0),1),0)
当我将其移至 WorkOrderItemInstructionPartCosts 视图时,我的报告产生了 10.82 美元。然后我将 *sitli.QuantityIssuedAtStockUOM
添加到行中,得到 259.73 美元。然后我将 ROUND 函数应用于 COALESCE 函数,瞧!正在生成正确的值 ($259.68)。
最后一行看起来像这样:
ROUND(COALESCE(dbo.GetItemAverageCost(ItemModel.IDItemModel) / ISNULL(NULLIF(UOMFactor, 0),1),0),2)*sitli.QuantityIssuedAtStockUOM
再次感谢所有帮助我解决此问题的人,对于没有准确的信息一开始感到抱歉。
最好,
乔纳森
我有一份提供信息的报告,但我得到的信息不一致,原因是 SQL 视图或视图中嵌套的 SQL 函数似乎存在问题。我已经尝试找到一种调试 SQL 视图的方法,但是,SSMS 似乎只会调试存储过程,所以我不太确定如何逐步执行并查看发生了什么。这真的让我难住了,我忍不住想知道这是否是一个舍入问题。
GetItemAverageCost RETURNS DECIMAL(12,2)
和 sitli.QuantityIssuedAtStockUOM 中的数据类型是 System.Int64 / bigint(旁注:我很困惑为什么 LINQPad 为该列显示 2 种数据类型。在左侧的树中,展开 sitli 后table 并将鼠标悬停在 QuantityIssuedAtStockUOM 上,气球 BigInt NOT NULL 会弹出,但是当我 Take(100) 并将鼠标悬停在结果集中的列上时,它会显示 System.Int64)。不管怎样,这是 COALESCE 函数。
COALESCE((dbo.GetItemAverageCost(ItemModel.IDItemModel)*sitli.QuantityIssuedAtStockUOM) / ISNULL(NULLIF(ItemModel.UOMFactor, 0),1),0) -- 259.73
--ROUND(COALESCE((dbo.GetItemAverageCost(ItemModel.IDItemModel)*sitli.QuantityIssuedAtStockUOM) / ISNULL(NULLIF(ItemModel.UOMFactor, 0),1),0),2) -- 259.73
--COALESCE(ROUND((dbo.GetItemAverageCost(ItemModel.IDItemModel)*sitli.QuantityIssuedAtStockUOM) / ISNULL(NULLIF(ItemModel.UOMFactor,2), 0),1),0) -- 259.70
--COALESCE((ROUND(dbo.GetItemAverageCost(ItemModel.IDItemModel),2)*sitli.QuantityIssuedAtStockUOM) / ISNULL(NULLIF(ItemModel.UOMFactor, 0),1),0) -- 259.73
原创/错误合并:
COALESCE(dbo.GetItemAverageCost(ItemModel.IDItemModel)*sitli.QuantityIssuedAtStockUOM,0)
我不确定还包括什么,但我没有在网上找到很多资源来深入了解这种情况。非常感谢您的宝贵时间。
编辑:GetItemAverageCost:
ALTER FUNCTION GetItemAverageCost
(
@IDItemModel varchar(8000)
)
RETURNS DECIMAL(16,4)
--RETURNS DECIMAL(12,2)
AS
BEGIN
RETURN
(
SELECT
COALESCE(AVG(poli.UnitPrice),0) as AvgCost
-- COALESCE(ROUND(AVG(poli.UnitPrice),0),2) as AvgCost 260.00
FROM ItemModel im
LEFT JOIN VendorItem vi
ON im.IDItemModel = vi.IDItemModel
JOIN POLineItem poli
ON vi.IDVendorItem = poli.IDVendorItem
WHERE
im.IDItemModel = @IDItemModel
GROUP BY
im.IDItemModel,
im.ItemNumber
)
END
修复;让你的函数 return 16,4 而不是 12,2 然后在乘以数量后舍入两位两位小数。
"When a given report is run, there are no errors thrown. But the calculations are off. For example a part number 12 shows a quantity of 24 were issued at a cost of 9.73. However, each part costs .82 so the calculation should be 9.68. I'm not sure where the difference of 5 cents is coming from. The 9.73 is the result of the COALESCE function above. Hopefully this makes sense"
运行 SQL 仅适用于独立于函数的第 12 部分,您会看到平均值为 10.822083333333333333333333333333(10.82 5/24ths)
- 24*单价 = 259.73 美元
- 单价 = 259.73/24
- 单价 = 10.82 美元 5/24。
您会看到差异为 $.05
- 10.82 5/24。 *24 = 259.73
- 10.82 * 24 = 259.68
5 美分的差异并没有平均分配到剩余的 24 美分中。因此在使用您的函数时出现舍入误差。
当你想到去商店买东西时,它总是等于一分钱。当你去加油站时,他们会收取最接近的 .00001 美分。 (或者在你的情况下是 4 位小数)
直到乘以数量或实际现金需要易手时,才进行四舍五入。如果做得太早,你会看到你看到的舍入错误。
因此,您消除了 over/under 收费舍入错误,最多您会比您应该少收或多收一分钱。
好的,非常感谢一路上提供帮助的所有人。有几个问题阻止我得到正确的答案。一方面,我大部分时间都在使用不正确的表达方式。其次,在我弄清楚要使用哪个表达式之后,接下来就是将 ROUND 函数放在正确的位置。
所以,我应该用来计算平均成本的表达式是:
COALESCE(dbo.GetItemAverageCost(Item.IDItemModel) / ISNULL(NULLIF(UOMFactor, 0),1),0)
当我将其移至 WorkOrderItemInstructionPartCosts 视图时,我的报告产生了 10.82 美元。然后我将 *sitli.QuantityIssuedAtStockUOM
添加到行中,得到 259.73 美元。然后我将 ROUND 函数应用于 COALESCE 函数,瞧!正在生成正确的值 ($259.68)。
最后一行看起来像这样:
ROUND(COALESCE(dbo.GetItemAverageCost(ItemModel.IDItemModel) / ISNULL(NULLIF(UOMFactor, 0),1),0),2)*sitli.QuantityIssuedAtStockUOM
再次感谢所有帮助我解决此问题的人,对于没有准确的信息一开始感到抱歉。 最好, 乔纳森