我有一个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语句生成的Distance字段似乎是以字符串形式返回的。如果我然后添加要求在0到45英里之间的位置的SQL代码,它将返回从“0”和“45”之间开始的任何距离值。这包括距离为“1017”英里的位置。显然,距离字段是文本字段,而不是数字字段。所以我不能使用“BETWEEN”声明。我也无法评估使用“<”和“>”因为它有同样的问题。
我将上面的SQL查询保存为名为“LocationSearch”的已保存查询。这样我可以对它运行二次查询,如下所示:
SELECT * FROM LocationSearch WHERE Distance < @MaxDistance
Access将询问@lat,@ long和@MaxDistance参数,然后将按记录集返回位置,按距离排序。但是,出现的问题是当我输入MaxDistance为45.当一个表包含美国西海岸的位置,@lat为47,@ long为-122(西雅图附近)时,Access返回以下内容:
另请注意,“距离”字段是右对齐格式的,因此它看起来像是一个数字字段,但由于某种原因,查询返回圣地亚哥的一个位置,距离为1,017英里。我的猜测是它将Distance字段评估为文本字段,而在ASCII比较中,我认为“1017”位于“0”和“45”之间。
另一件事:我使用ASP 3.0(经典)使用JET OLEDB 4.0访问此查询。
任何人都知道如何将距离字段定义为数字?
谢谢!
---编辑---
在下面的答案中使用HansUp的想法,我尝试了这个查询来强制Access将Distance字段视为单个精度数字:
SELECT * FROM LocationSearch WHERE CSng(Distance) < @MaxDistance
即使这样也返回了与以前完全相同的结果,其中包括位于1017英里外的圣地亚哥的位置。
答案 0 :(得分: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
...如果这对任何事情都有意义。 : - )
答案 1 :(得分:1)
我在没有select *
且没有FROM
和ORDER 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语句的代码中,而不是在语句或jet引擎本身中。
答案 2 :(得分:1)
好的,解决了!
HansUp,您的想法最终成为了解决方案。我尝试在SQL查询中的CSng()
参数上添加@MaxDistance
函数,这就是解决它的问题。
以下是修改后的辅助SQL查询:
SELECT * FROM LocationSearch WHERE CSng(Distance) < CSng(@MaxDistance)
感谢大家的帮助!你们都摇滚。
新年快乐。