我需要从当前用户位置获取数据库表中最近的机场。我找到了这个公式:https://de.scribd.com/presentation/2569355/Geo-Distance-Search-with-MySQL#page=7
因此,上面链接中描述的公式与我目前的情况之间存在一些差异:示例是在MySQL中,我使用的是MS SQL(我猜不是问题)。 lat
和lon
被视为具有numeric
数据类型的数据库列,但由于某种原因,数据库表是使用两个类型为varchar
的相应列创建的。
我的问题是:当我想使用ORDER BY
子句时,它会抛出Error converting data type nvarchar to numeric
,如果没有它,它就会起作用。我做了一些关于什么垃圾作为字符串插入并进行迁移的研究,以便我只有一些空值。
我不能全部因为我只需要一个。但如果我TOP 1
没有ORDER BY
,我就不会在任何机场而不是最近的机场。有谁知道如何修复查询?
提前致谢!
SELECT TOP 1
temp.Distance
FROM (
SELECT
(
3956 * 2 * ASIN(
SQRT(
POWER(
SIN((53.6349994 - abs(CAST(latitude_deg AS numeric))) * pi() / 180 / 2), 2) + COS(53.6349994 * pi()/180) * COS(abs(CAST(latitude_deg AS numeric)) * pi()/180) * POWER(SIN((10.0117336 - CAST(longitude_deg AS numeric)) * pi()/180 / 2), 2) ))) AS Distance
FROM Airport_Airports
WHERE
isnumeric(longitude_deg) = 1 AND isnumeric(latitude_deg) = 1 AND
longitude_deg LIKE '%[^0-9.]%' AND latitude_deg LIKE '%[^0-9.]%'
) AS temp
WHERE
temp.Distance < 50000
Order BY
temp.Distance
答案 0 :(得分:2)
首先,这个逻辑没有意义:
WHERE isnumeric(longitude_deg) = 1 AND
isnumeric(latitude_deg) = 1 AND
longitude_deg LIKE '%[^0-9.]%' AND
latitude_deg LIKE '%[^0-9.]%'
like
正在寻找非数字字符。我想你打算:
WHERE isnumeric(longitude_deg) = 1 AND
isnumeric(latitude_deg) = 1 AND
longitude_deg NOT LIKE '%[^0-9.]%' AND
latitude_deg NOT LIKE '%[^0-9.]%'
这可确保值为数字。
问题的解决方案 - 至少在SQL Server 2012+中 - 是使用try_convert()
或try_cast()
:
(3956 * 2 * ASIN(
SQRT(
POWER(
SIN((53.6349994 - abs(try_convert(numeric, latitude_deg))) * pi() / 180 / 2), 2) + COS(53.6349994 * pi()/180) * COS(abs(try_convert(numeric, latitude_deg)) * pi()/180) * POWER(SIN((10.0117336 - try_convert(numeric, longitude_deg)) * pi()/180 / 2), 2) ))) AS Distance
这可以防止任何转换错误。
你不应该只使用numeric
。使用浮点表示或带小数位的东西,比如numeric(20, 10)
。
order by
发生这种情况的原因是因为SQL优化器。您显然有一些lat / long值无法正确转换为numeric
。 SQL Server允许自己重新安排操作,因此转换可能在过滤之前由<{1}}子句进行过滤。这是整体查询优化的一部分。