我有SQL function使用他们的lat / lng坐标计算两点之间的距离。使用此功能,我可以根据给定点的距离从大型集合( GEOCODES表)中列出一组位置,如下所示:
DECLARE @LAT1 float, @LNG1 float,
SET @LAT1 = '34.169540'
SET @LNG1 = '-92.590990'
SELECT E.* FROM GEOCODES E
WHERE dbo.fnGetDistance(E.lat, E.lng, @LAT1, @LNG1, 'miles') < '20'
我有第二张表格( GEOMILES ),表格中各点之间的距离为:
LOCATION1 | STATE1 | LOCATION2 | STATE2 | DISTANCE
-----------+---------+-------------+----------+---------
New York | NY | Boston | MA | 220
我想要实现的是SELECT
查询,如果出发点在纽约20英里范围内,并且到达点在波士顿20英里范围内,则返回220的距离。到目前为止,我有这个,但是当我通过手动检查lat / lng点等加起来时它没有返回任何内容。非常感谢任何帮助!
DECLARE @FROM_LOC VARCHAR(100), @FROM_STA VARCHAR(2), @TO_LOC VARCHAR(100), @TO_STA VARCHAR(2)
SET @FROM_LOC = 'NEWARK'
SET @FROM_STA = 'NJ'
SET @TO_LOC = 'MEDFORD'
SET @TO_STA = 'MA'
SELECT G.DIST FROM GEOMILES G, GEOCODES E
JOIN GEOCODES C ON C.asciiname = @FROM_LOC AND C.admin1 = @FROM_STA
JOIN GEOCODES D ON D.asciiname = @TO_LOC AND D.admin1 = @TO_STA
WHERE dbo.fnGetDistance(E.lat, E.lng, C.lat, C.lng, 'miles') < '20'
AND dbo.fnGetDistance(E.lat, E.lng, D.lat, D.lng, 'miles') < '20'
答案 0 :(得分:1)
我认为这就是你所追求的(使用你的表结构)。 。
SELECT G.DIST
FROM GEOMILES G
, GEOCODES F --from airport
, GEOCODES E --to airport
, GEOCODES C --from location
, GEOCODES D --to location
WHERE C.asciiname = @FROM_LOC
AND C.admin1 = @FROM_STA
AND D.asciiname = @TO_LOC
AND D.admin1 = @TO_STA
AND dbo.fnGetDistance(F.lat, F.lng, C.lat, C.lng, 'miles') < 20
AND dbo.fnGetDistance(E.lat, E.lng, D.lat, D.lng, 'miles') < 20
and G.Location1 = F.asciiname
and G.Location2 = E.asciiname
and G.State1 = F.admin1
and G.State2 = E.admin1
备用版本(我认为这会更好)
SELECT G.DIST
FROM GEOMILES G
inner join
(
select fromAirport.asciiname
, fromAirport.admin1
from GeoCodes fromAirport
where exists
(
select top 1 1
from GeoCodes fromLocation
where fromLocation.asciiname = @FROM_LOC
and fromLocation.admin1 = @FROM_STA
and dbo.fnGetDistance(fromLocation.lat, fromLocation.lng, fromAirport.lat, fromAirport.lng, 'miles') < 20
)
) fromA
on G.Location1 = fromA.asciiname
and G.State1 = fromA.admin1
inner join
(
select toAirport.asciiname
, toAirport.admin1
from GeoCodes toAirport
where exists
(
select top 1 1
from GeoCodes toLocation
where toLocation.asciiname = @TO_LOC
and toLocation.admin1 = @TO_STA
and dbo.fnGetDistance(toLocation.lat, toLocation.lng, toAirport.lat, toAirport.lng, 'miles') < 20
)
) toA
on G.Location1 = toA.asciiname
and G.State1 = toA.admin1
答案 1 :(得分:0)
检查您的WHERE
条款,您似乎正在寻找距离开始和结束位置20英里内的所有代码 - 您已经指定距离相隔220英里。
此外,您将显式JOIN
与隐式({逗号分隔FROM
子句)混合在一起。请明确限定所有联接;除其他事项外,G
和E
应该如何相互关联?
答案 2 :(得分:0)
这是我尝试解决方案 - 我已经在这里使用GEOGRAPHY来保存表格的脚本,但希望您可以根据自己的需要轻松调整 - 如果不是,请让我知道&amp;我会适应:
--setup
declare @OneMileInMeters int = 1609
declare @t table
(
id bigint not null identity(1,1) primary key clustered
, name nvarchar(64)
, lat float
, long float
, geo geography null
)
insert @t
select 'Seattle', 47.455, -122.2310, null
union select 'Boston', 42.372, -71.0298, null
union select 'Chicago', 41.953, -87.6430, null
union select 'Spokane', 47.668, -117.5290, null
union select 'Philly', 39.888, -75.2510, null
union select 'NY', 40.7142, -74.0064, null
union select 'Newark', 40.7356, -74.1728, null
union select 'Medford', 42.4183, -71.1067, null
update @t
set geo = geography::Point(lat, long, 4326)
--query
declare @fromLoc nvarchar(64) = 'Newark'
, @toLoc nvarchar(64) = 'Medford'
, @maxDistanceToAirport int = 20 * @OneMileInMeters
select f2.name AirportFrom, t2.name AirportTo, f2.geo.STDistance(t2.geo) / @OneMileInMeters FlightDistance
from @t f
, @t t
, @t f2
, @t t2
where f.name = @fromLoc
and t.name = @toLoc
and f.geo.STDistance(f2.geo) < @maxDistanceToAirport
and t.geo.STDistance(t2.geo) < @maxDistanceToAirport
and t.id != t2.id
and f.id != f2.id