Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to select using lat/lng radius with a SQL join

I have a SQL function that calculates the distance between two points using their lat/lng coordinates. Using this function, I can shortlist a set of locations from a large set (GEOCODES table) based on their distance for a given point like so:

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'

I have a second table (GEOMILES) with distances between points in the form:

LOCATION1  | STATE1  |  LOCATION2  |  STATE2  | DISTANCE
-----------+---------+-------------+----------+---------
New York   |   NY    |    Boston   |   MA     |   220

What I'm trying to achieve is a SELECT query that returns a distance of 220 if a departure point is within 20 miles of New York, and an arrival point is within 20 miles of Boston. So far, I have this but it returns nothing when I know from checking manually that the lat/lng points etc add up. Any help is much appreciated!

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'
like image 575
greener Avatar asked Feb 22 '26 23:02

greener


1 Answers

I think this is what you're after (using you table structure). . .

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

Alternate version (I think this will perform better)

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
like image 75
JohnLBevan Avatar answered Feb 25 '26 12:02

JohnLBevan



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!