1

我有一个 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 英里外的圣地亚哥的位置。

4

3 回答 3

2

如果您找不到从该Duration字段表达式返回数值而不是文本的方法,请将您的查询用作子查询,然后强制转换Duration为包含查询。

SELECT CSng(sub.Duration) AS Duration_as_single
FROM
    (
        -- your existing query --
    ) AS sub
WHERE CSng(sub.Duration) BETWEEN 0 AND 45
ORDER BY 1;

这种方法也可以带来更好的ORDER BY……如果这很重要的话。:-)

于 2013-01-04T20:41:47.920 回答
1

select *我在没有, 和FROMandORDER BY子句的情况下尝试了您的查询。我在 中添加了一个额外的列,SELECT以证明字符串在访问网格中以左对齐形式返回。

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, 
'test' as test

我被提示输入四个参数,但最后,我得到了一个包含两列的表格:

在此处输入图像描述

由于第一列是右对齐的,而第二列(显然是一个字符串)是左对齐的,看来访问确实将它作为数字返回给我。这是在 Access 2010 中。

--编辑--

我刚刚创建了一个名为Locations. 它有一个字段id(自动编号)和一个字段Field1(文本)。我运行了 OP 提供的原始查询,它工作正常(距离以数字形式返回)。

这导致了怀疑...... OP 的Locations表是否有它自己的距离字段,即字符串?否则,问题一定出在调用 SQL 语句的代码中,而不是语句或喷气发动机本身。

于 2013-01-04T20:31:27.120 回答
1

好的,解决了!

HansUp,你的想法原来是解决方案。我尝试在 SQL 查询中CSng()的参数上添加函数,@MaxDistance这就是修复它的原因。

这是修改后的辅助 SQL 查询:

SELECT * FROM LocationSearch WHERE CSng(Distance) < CSng(@MaxDistance)

谢谢大家的帮助!你们都摇滚。

新年快乐。

于 2013-01-04T22:30:41.733 回答