我有一个 SQL 语句(在 Access 中保存为“LocationSearch”)计算两点之间的距离并将“距离”作为生成的字段返回。
SELECT Int((3963*(Atn(-(Sin(LATITUDE/57.2958)*
Sin([@lat]/57.2958)+Cos(LATITUDE/57.2958)*Cos([@lat]/57.2958)*
Cos([@lng]/57.2958-LONGITUDE/57.2958))/Sqr(-(Sin(LATITUDE/57.2958)*
Sin([@lat]/57.2958)+Cos(LATITUDE/57.2958)*Cos([@lat]/57.2958)*
Cos([@lng]/57.2958-LONGITUDE/57.2958))*(Sin(LATITUDE/57.2958)*
Sin([@lat]/57.2958)+Cos(LATITUDE/57.2958)*Cos([@lat]/57.2958)*
Cos([@lng]/57.2958-LONGITUDE/57.2958))+1))+2*Atn(1)))*10)/10 AS Distance, *
FROM Locations
ORDER BY (3963*(Atn(-(Sin(LATITUDE/57.2958)*
Sin([@lat]/57.2958)+Cos(LATITUDE/57.2958)*Cos([@lat]/57.2958)*
Cos([@lng]/57.2958-LONGITUDE/57.2958))/Sqr(-(Sin(LATITUDE/57.2958)*
Sin([@lat]/57.2958)+Cos(LATITUDE/57.2958)*Cos([@lat]/57.2958)*
Cos([@lng]/57.2958-LONGITUDE/57.2958))*(Sin(LATITUDE/57.2958)*
Sin([@lat]/57.2958)+Cos(LATITUDE/57.2958)*Cos([@lat]/57.2958)*
Cos([@lng]/57.2958-LONGITUDE/57.2958))+1))+2*Atn(1)));
您看到的所有讨厌的数学代码都是在 SQL 语句中使用纬度和经度坐标计算距离(以英里为单位)。
但是,问题在于 SQL 语句生成的距离字段似乎是作为字符串返回的。如果我随后添加 SQL 代码来询问 0 到 45 英里之间的位置,它会返回从“0”到“45”之间的任何距离值。这包括距离“1017”英里的位置。显然,距离字段是文本字段,而不是数字字段。所以我不能使用“BETWEEN”语句。我也无法使用“<”和“>”进行评估,因为它有同样的问题。
我将上面的 SQL 查询保存为名为“LocationSearch”的已保存查询。这样我就可以对它运行辅助查询,如下所示:
SELECT * FROM LocationSearch WHERE Distance < @MaxDistance
Access 将询问@lat、@long 和@MaxDistance 参数,然后位置将在记录集中返回,按距离排序。但是,出现的问题是当我输入 45 的 MaxDistance 时。使用包含美国西海岸位置的表,以及 47 的 @lat 和 -122 的 @long(西雅图附近),Access 返回以下:
另请注意,“距离”字段的格式是正确的,因此它看起来是一个数字字段,但由于某种原因,查询返回了圣地亚哥的一个位置,该位置距离 1,017 英里。我的猜测是它将距离字段评估为文本字段,并且在 ASCII 比较中,我相信“1017”位于“0”和“45”之间。
另一件事:我正在使用 ASP 3.0(经典)使用 JET OLEDB 4.0 访问此查询。
有人知道如何将距离字段定义为数字吗?
谢谢!
- - 编辑 - -
使用 HansUp 在下面的回答中的想法,我尝试了此查询以强制 Access 将距离字段视为单精度数:
SELECT * FROM LocationSearch WHERE CSng(Distance) < @MaxDistance
即使这样也返回了与以前完全相同的结果,其中包括 1017 英里外的圣地亚哥的位置。