意外的 SQL 除法结果?

Unexpected SQL division results?

我使用SQL服务器。

与部门合作,我在这两个查询中收集了我的发现,您可以使用 SQL 服务器版本重现它们。

我原以为带整数的除法在两种情况下都具有相同的值。 因为无论 table 中的值如何,如果我得到意想不到的结果,我最终会遇到一个逻辑错误,有时很难调查。

SQL答:

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乙:

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

您的第一个 table 全部是整数。

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

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

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

编辑

经过你最后的评论,我更加理解你的问题了。当您将不同的数据类型联合在一起时,您在第二个 CTE 中所做的,SQL 服务器将隐式地将它们转换为必要的数据类型以伴随所有输入。 See the order of precedence here

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

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

select * from s

如果您想对这两个数据集获得相同的结果,请使用 FLOOR() 函数

SQL一个

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