意外的SQL除法结果?

时间:2017-09-05 19:33:16

标签: sql sql-server-2008 division

我使用的是SQL Server。

使用部门我在这两个您可以使用SQL Server版本重现的查询中收集了我的发现。

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

SQL A:

left

结果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; 

SQL B:

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

结果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; 

2 个答案:

答案 0 :(得分:5)

你的第一张桌子全是整数。

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

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

select 3/10为0而不是。{3000},select 3/10.0。如果要返回decimal / float,则分子或分母必须是float(或两者)

修改

在您上次发表评论后,我更了解您的问题。当您将不同的数据类型组合在一起时(在第二个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

答案 1 :(得分:1)

如果要为这两个数据集获得相同的结果,请使用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