【问题标题】:SQL 1 Digit Before The Decimal PlaceSQL 小数位前 1 位
【发布时间】:2021-01-05 07:23:24
【问题描述】:

我将总数的比率存储在表格中,因此我知道我只会有 0 到 1 之间的值,并且小数点后 4 位足够精确。因此,我将表格列创建为DECIMAL(5,4)

在计算人口数据时,我发现了一个奇怪的行为,其中 SQL 似乎需要在小数点前多出 2 位,所以如果我使用 DECIMAL(5,4)DECIMAL(6,4) 我会收到 Arithmetic overflow error converting int to data type numeric. 错误。我必须将它推到DECIMAL(7,4) 以获取分隔线的一侧,然后将整个分隔线包裹在另一个演员表中以获得我实际需要的精度。

SQL 将每个不同的精度视为不同的数据类型,从而调用转换,因此我意识到在大规模完成时会增加工作量,因为我无法直接转换为 DECIMAL(5,4) 我将其存储为。我也很好奇是什么导致了这种情况。

下面的例子演示了这个问题。它应该适用于DECIMAL(2,1),但它只能适用于DECIMAL(3,1)。即使这样,结果也精确到小数点后 6 位。谁能至少解释一下这里发生了什么,并希望有一种方法可以避免它而不用加倍演员表?

DECLARE @SalesTable TABLE (ProductId INT, Size NVARCHAR(2), Quantity INT)
INSERT INTO @SalesTable VALUES (123, 'S', 5), (123, 'M', 20), (123, 'L', 15), (123, 'XL', 10)

SELECT Size, sales.Quantity / CAST(sales.Total AS DECIMAL(3,1)) AS SalesRatio
FROM (
    SELECT Size, Quantity, SUM([Quantity]) OVER (PARTITION BY ProductId) AS Total
    FROM @SalesTable
) AS sales

使用额外的小数并产生不同精度的结果

Size    SalesRatio
S       0.100000
M       0.400000
L       0.300000
XL      0.200000

【问题讨论】:

    标签: sql sql-server sql-server-2008-r2


    【解决方案1】:

    我真的不明白你的困惑。在您的示例中,salesTotal1 的值为 50。这需要小数点左侧两位数。

    也许混淆在于小数的内部类型。虽然乘法的规则很复杂,除法的规则非常神秘,但加法的规则要简单得多:类型不会改变。

    所以,总数需要适合十进制值。

    如果你关心算术运算的结果的类型,那么转换整个表达式:

    SELECT Size,
           CAST(sales.Quantity * 1.0 / sales.Total AS DECIMAL(3,1)) AS SalesRatio
    

    * 1.0 可能不是必需的,但它确保除法有小数位。

    【讨论】:

    • * 1.0 是绝对需要的,而我在 1 次拍摄中所缺少的。在我的真实代码中,我没有看到将较大组件向下转换的错误,然后在我创建简单示例时又看不到它。谢谢
    【解决方案2】:

    小数精度应设置为包含计算中包含的最大数字所需的最大长度(除非另有处理)。在这种情况下,数量是数据类型 INT,其最小值/最大值为 -2^31 (-2,147,483,648) 到 2^31-1 (2,147,483,647)。要涵盖所有情况,您可以将数据类型设为 Decimal(16, 4)。任意整数 12 位 + 小数点右侧 4 位。如果将 1.0 添加或乘以商的分母,SQL Server 会自动扩展小数精度。像这样的

    DECLARE @SalesTable TABLE (ProductId INT, Size NVARCHAR(2), Quantity INT)
    INSERT INTO @SalesTable VALUES (123, 'S', 5), (123, 'M', 20), (123, 'L', 15), (123, 'XL', 10)
    
    SELECT Size, cast(sales.Quantity / (sales.Total*1.0) AS DECIMAL(16,4)) AS SalesRatio
    FROM (
        SELECT Size, Quantity, SUM([Quantity]) OVER (PARTITION BY ProductId) AS Total
        FROM @SalesTable
    ) AS sales;
    

    输出

    Size    SalesRatio
    S       0.1000
    M       0.4000
    L       0.3000
    XL      0.2000
    

    【讨论】:

      猜你喜欢
      • 2015-11-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多