我理解比较花车的问题,并在这种情况下对它们的使用感到遗憾 - 但我不是桌面作者,只有很小的障碍可以爬......
有人决定使用浮点数,因为你期望使用GUID。我需要检索具有特定浮点值的所有记录。
sp_help MyTable
-- Column_name Type Computed Length Prec
-- RandomGrouping float no 8 53
这是我天真的尝试:
--yields no results
SELECT RandomGrouping
FROM MyTable
WHERE RandomGrouping = 0.867153569942739
这是一个近似有效的尝试:
--yields 2 records
SELECT RandomGrouping
FROM MyTable
WHERE RandomGrouping BETWEEN 0.867153569942739 - 0.00000001
AND 0.867153569942739 + 0.00000001
-- 0.867153569942739
-- 0.867153569942739
在我天真的尝试中,字面意思是浮点文字吗?或者它是否真的是一个后来转换的十进制文字?
如果我的文字不是浮点文字,那么制作浮点文字的语法是什么?
编辑:另一种可能性发生在我身上......可能是这个列中存储的数字比显示的更精确。可能无法创建表示此数字的文字。我会接受证明情况就是这样的答案。
编辑:对DVK的回应。
TSQL是MSSQLServer的SQL方言。
此脚本有效,因此可以在float类型之间确定性地执行相等性:
DECLARE @X float
SELECT top 1 @X = RandomGrouping
FROM MyTable
WHERE RandomGrouping BETWEEN 0.839110948199148 - 0.000000000001
AND 0.839110948199148 + 0.000000000001
--yields two records
SELECT *
FROM MyTable
WHERE RandomGrouping = @X
我说“大约”因为该方法测试范围。使用该方法,我可以获得不等于我的预期值的值。
链接的文章不适用,因为我不是(故意)试图跨越十进制和浮点数之间的世界边界。我正在努力只使用花车。这不是关于小数点到浮点数的不可转换性。
回应Zinglon:
可以找到我的记录的文字值,谢谢。
DECLARE @Y binary(8)
SET @Y = 0x3FEAD9FF34076378
SELECT *
FROM MyTable
WHERE convert(binary(8), RandomGrouping) = @Y
有可能在显示时截断这些值。我假设列没有对它的唯一约束,否则问题将没有实际意义。在我的设置中,SSMS会截断此脚本中更精确的值。
create table flt ( f float not null primary key )
insert into flt
select 0.111111111111111
union all
select 0.1111111111111111
select f, cast(f as binary(8)) from flt
类似地,如果这些值是不同的,您可以将它们转换为二进制(8)并基于该值识别它们,如下所示:
select f from flt
where cast(f as binary(8)) = 0x3FBC71C71C71C71C
这个文字是一个浮点文字吗?或者它是否真的是一个后来转换的十进制文字?
如果我的文字不是浮点文字,那么制作浮点文字的语法是什么?
SQL Server中的0.867153569942739
文字是decimal
类型,而不是float
。引擎自动选择适当的比例和精度来表示给定的文字。
要写一个float
类型的文字,你应该使用科学记数法,如下所示:0.867153569942739E0
这在Constants (Transact-SQL)中有记载
十进制常数
十进制常量由一串数字表示,这些数字未用引号括起来并包含小数点。以下是十进制常量的示例:
1894.1204 2.0
浮点数和实常数
浮点数和实常数用科学记数法表示。以下是浮点值或实数值的示例:
101.5E5 0.5E-2
sp_describe_first_result_set
可以告诉我们列的类型
EXEC sp_describe_first_result_set N'SELECT 0.867153569942739, 0.867153569942739E0'
它返回第一列的numeric(15,15)
和第二列的float
。
如果您的列RandomGrouping
已编入索引,则使用float
文字会更有效,因为当您在RandomGrouping
中包装convert()
时,无法使用索引。
以下查询将使用索引:
SELECT *
FROM MyTable
WHERE RandomGrouping = 0.867153569942739E0
以下查询将不使用索引:
SELECT *
FROM MyTable
WHERE convert(binary(8), RandomGrouping) = @Y
问题不在于它是否是浮点字面量。
问题是在Sybase(或任何数据库服务器)中比较两个浮点的相等性是不确定的,因为4.00000000000000000000 ...和3.99999999999999999999 ...是相同的确切数但不相等。
你的第二个解决方案是唯一正确的方法来比较浮点数的“相等性”(也就是说,它们是否与精度相同)。
你为什么要对你的第二种方法说“近似工作”?
既然你没有提供你使用的特定数据库服务器,这里有一个相当不错的问题报告(与上面的结论基本相同)对于MySQL
http://dev.mysql.com/doc/refman/5.0/en/problems-with-float.html