意外的 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 服务器必须选择 INT
或 FLOAT
。如果选择 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
我使用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 服务器必须选择 INT
或 FLOAT
。如果选择 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