【问题标题】:Unexpected SQL division results?意外的 SQL 除法结果?
【发布时间】:2017-09-05 19:33:15
【问题描述】:

我使用 SQL Server。

与部门合作,我在这两个查询中收集了我的发现,您可以使用您的 SQL Server 版本重现这些结果。

我期望 Division with Integer 在两种情况下都具有相同的值。 因为无论我的表中的值如何,如果我得到意想不到的结果,我最终会遇到一个逻辑错误,有时很难调查。

SQL A:

WITH s AS (
    SELECT 'Integer' AS c, 1 AS k UNION
    SELECT 'Float', 1 UNION
    SELECT 'NULL', NULL
) 
SELECT 
    c AS [Type],
    k/10 AS                          'Division',
    CAST(k as numeric(38,4))/10 AS 'Cast',
    COALESCE(k, 0)/10           AS 'Coalesce',
    COALESCE(k, .0)/10          AS 'Coalesce with float'
FROM s; 

结果 A

Type        Division    Cast        Coalesce    Coalesce with float
Float       0           0.100000    0           0.100000
Integer     0           0.100000    0           0.100000
NULL        NULL        NULL        0           0.000000

SQL B:

WITH s AS (
    SELECT 'Integer' AS c, 1 AS k UNION
    SELECT 'Float', .1 UNION
    SELECT 'NULL', NULL
) 
SELECT 
    c AS [Type],
    k/10 AS                          'Division',
    CAST(k as numeric(38,4))/10 AS 'Cast',
    COALESCE(k, 0)/10           AS 'Coalesce',
    COALESCE(k, .0)/10          AS 'Coalesce with float'
FROM s; 

结果 A

Type        Division    Cast        Coalesce    Coalesce with float
Float       0.010000    0.010000    0.010000    0.010000
Integer     0.100000    0.100000    0.100000    0.100000
NULL        NULL        NULL        0.000000    0.000000

【问题讨论】:

    标签: sql sql-server-2008 division


    【解决方案1】:

    您的第一个表全是整数。

    SELECT 'Float', 1 is an INT 不是一个浮点数,因为你把这个词放在那里。它将被暗示为 INT,因为没有小数位。

    然后,您知道整数除法使用整数...例如...

    select 3/10 是 0,而不是使用 select 3/10.0 得到的 .3000。如果要返回小数/浮点数,则分子或分母必须是浮点数(或两者)

    编辑

    在您上次发表评论后,我更了解您的问题。当您将不同的数据类型联合在一起时,就像您在第二个 CTE 中所做的那样,SQL Server 将隐式地将它们转换为必要的数据类型以伴随所有输入。 See the order of precedence here

    因此,如果您只是从该 cte 中选择 *... 您将看到您的 1 已转换为 1.0。一列只能有一个数据类型。在此示例中,SQL Server 必须选择 INTFLOAT。如果选择了 INT,您将遇到数据完整性问题。

    WITH s AS (
        SELECT 'Integer' AS c, 1 AS k UNION
        SELECT 'Float', .1 UNION
        SELECT 'NULL', NULL
    ) 
    
    select * from s
    

    【讨论】:

    • 请检查第二条语句 SELECT 'Float', .1
    • @profimedica 在第二条语句中,你有一个小数点。它与 0.1 相同。第一个中缺少这一点,这就是您的整数除法返回整数的原因。
    • 我必须强调我创建两个场景时都知道添加点以创建浮动的效果。我也期望整数除法的结果产生一个整数,而浮点数的结果产生一个浮点数。这是两个示例中第一行的情况。意外的结果出现在 Integer 行上,其中参与者相同,但输出的类型由浮点结果决定。
    【解决方案2】:

    如果您希望这两个数据集的结果相同,请使用 FLOOR() 函数

    SQL A

    WITH s AS (
        SELECT 'Integer' AS c, 1 AS k UNION
        SELECT 'Float', 1 UNION
        SELECT 'NULL', NULL
    ) 
    SELECT c AS [Type],
           FLOOR(k/10) AS 'Division',
           CAST(k as numeric(38,4))/10 AS 'Cast',
           FLOOR(COALESCE(k, 0)/10) AS 'Coalesce',
           COALESCE(k, .0)/10 AS 'Coalesce with float'
    FROM s; 
    

    SQL B

    WITH s AS (
        SELECT 'Integer' AS c, 1 AS k UNION
        SELECT 'Float', .1 UNION
        SELECT 'NULL', NULL
    ) 
    SELECT 
        c AS [Type],
        FLOOR(k/10) AS 'Division',
        CAST(k as numeric(38,4))/10 AS 'Cast',
        FLOOR(COALESCE(k, 0)/10) AS 'Coalesce',
        COALESCE(FLOOR(k), .0)/10 AS 'Coalesce with float'
    FROM s; 
    

    两个查询的结果

    Type    Division    Cast        Coalesce    Coalesce with float
    Float   0           0.100000    0           0.100000
    Integer 0           0.100000    0           0.100000
    NULL    NULL        NULL        0           0.000000
    

    【讨论】:

    • 在你的 SQL B floor 中,结果是一个整数,它被 oalesce 转换回浮点数:COALESCE(FLOOR(k), .0)。事实上,你的方法将强制结果的类型,scsimon 解释说类型优先级是为整个列决定的。
    猜你喜欢
    • 1970-01-01
    • 2023-03-12
    • 2012-02-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-05
    • 1970-01-01
    相关资源
    最近更新 更多