【问题标题】:Using LIKE to match floats when Rounding is not wanted不需要舍入时使用 LIKE 匹配浮点数
【发布时间】:2013-04-11 13:57:02
【问题描述】:

这就是我想要完成的。我在两个表中有坐标数据,我试图将它们与关联表链接在一起。这是一对一的关联,所以如果我在表 A 中有 40 条记录,在表 B 中有 40 条记录,那么我应该在关联表中有 40 条记录。

现在这两个表中的数据大致相同,但绝不相同,实际上它们甚至很少具有相同的精度。一个表(我们会说 A)总是有 6 个小数位,而表 B 可能没有小数位或最多 6 个小数位。

假设我们只是将表 A 中的 12.345678 与表 B 中的一对数据与 12.34 进行匹配。

所以我在我的 asp.net 代码中有一个 foreach,它强制将零放在表 B 数据的末尾,所以我们首先将 12.345678 与 12.340000 进行比较。

然后是 12.34567 对 12.34000。 然后 12.3456 对 12.3400 然后是 12.345 对,12.340

然后是 12.34,反对,12.34。

只要不存在关联记录,包含对表 A 中的 12.345678 或表 B 中的 12.34 的引用,就会创建一个新的关联记录。

现在您可能会问,Joe,那么您如何比较表 A 中的数据和表 B 中的数据?我把这部分放在最后,因为它是最奇怪的。

我正在使用 LIKE,我相信这会让一些人感到不安,因为你已经在想,“你到底为什么要使用 LIKE,它是用于浮点数的字符串匹配?”

因为它是目前为止效果最好的,大约 95% 的时间。其他 5% 的大部分只是因为数据差异太大,但有一个非常奇怪的子集绝对应该匹配。

所以在插入记录之前,我会检查匹配项,只要我只有一个匹配项,我就会创建关联记录。

SELECT COUNT(*) FROM dbo.StartCoord 

WHERE StartLatitude LIKE '12.817%' 
AND StartLongitude LIKE '12.819%'

现在我正在查看 12.817 和 12.819 的来源记录,完整值实际上是 12.8179 和 12.8199。所以它应该有效,并且在 95% 的时间里它确实有效。

现在对于奇怪的部分,也许,使用 LIKE(应该只用于字符串匹配)导致 SQL Server 在后台进行舍入。我上面的stmt不起作用,但是如果我把它扔到Microsoft SQL Server Management中,并将其更改为...

SELECT COUNT(*) FROM dbo.StartCoord 

WHERE StartLatitude LIKE '12.817%' --trying to string match 12.8179
AND StartLongitude LIKE '12.82%'   --trying to string match 12.8199

...它有效!

我假设有人会说它实际上不是 LIKE,但事实上我将 LIKE '12.817%' 与浮点数进行比较,并且该浮点数导致 SQL Server 制定了一些舍入机制。

但是,如果是这样,为什么 LIKE '12.817%' 会匹配原始的 12.8179?是不是也应该没有四舍五入,只匹配 12.82 的情况?

读完这篇文章后,如果有人有更好的标题,我可以为以后遇到同样问题的其他人使用,那就太好了。

谢谢。

编辑:所以我完全忘了提及为什么采用这种方法。在一个表中,实际数据最多存储六个小数位,我想我一直将其用作表 A 的示例。但是,表 B 中的数据从无小数位到六位不等,有时会四舍五入,有时则不会。

因此,在表 A 中,我们可能有 12.123456,在某些情况下,它们给我们的表 B 数据可能是 12.1234,有时可能是 12.1235。他们给我们数据的方式并不一致,这就是我以这种方式解决它的原因。使用舍入或强制转换(数字)来处理这两种情况会导致创建的关联更少,但我才刚刚开始尝试。我还发现了一个我感兴趣的 STR() 函数。

【问题讨论】:

  • +1 问题的详细程度很好,方法很糟糕......
  • 我确定您指的是 LIKE。我发现的有关此问题的所有其他内容都涉及舍入,这大大降低了我创建关联的成功率。
  • 看了你的详细解释后,我还是不确定你到底想根据什么来比较?既然我假设您想匹配具有“相似”值的记录,那么计算两个浮点值之间的差异,然后根据小于 X 的差异进行过滤不是更好吗?
  • 在我对这种方法的关注列表中,like 的使用实际上相当低 - 更重要的是 (i) 为比较基础给出的唯一描述是当前的使用的流程,即使您不了解该流程,以及 (ii) 使用 for each 循环来处理关系数据库中的数据。
  • @CBroe - 试过了,我的例子非常简单。我实际上是在对表 A 和 B 中存在的 4 条不同的数据进行比较。问题变成了如何在 3/4 值非常接近而另一个值偏离的记录或 4/ 的记录之间进行选择4 个值有些接近;然而,两者都同样接近真实记录。

标签: sql decimal rounding sql-like


【解决方案1】:

如果您不想改变使用 LIKE。您可以将浮点数转换为小数,然后转换为 nvarchar,这应该会停止舍入问题。

SELECT COUNT(*) FROM dbo.StartCoord 
WHERE CAST(CAST(StartLatitude  as DECIMAL(12,6)) as nvarchar(20)) LIKE '12.817%' 
AND   CAST(CAST(StartLongitude as DECIMAL(12,6)) as nvarchar(20)) LIKE '12.819%'

我假设你只需要 6 位小数。

【讨论】:

  • 目前可行,但我无法投票。我将把它以及我可能能够工作的一些效率付诸实践。由于我显然做错了什么,因此试图采取马克的领导并为关系数据库查找良好的编码实践。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-12-28
  • 1970-01-01
  • 2021-01-04
  • 1970-01-01
  • 2020-06-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多