简体   繁体   中英

Is there a way to compare Lat/long of two tables

I have two tables:

  • address_points

  • kmldata

    address_points table columns: ID address Latitude1 Longitude2 kmldata table columns: Locname Lat Long

Now I want to see all the records of the address_points table whose Latitude1 and Longitude2 values fall in the range of Lat and Long values of kmldata table.

I have not handled comparison of locations before in the SQL server so don't know which function I can use here. I thought of the BETWEEN operator but can seem to use it here properly here. Any guidance on how I can acheive this?

You need to use the spatial functions within SQL Server. First you will need to aggregate all the points in your kmldata table to create an area, and then use STWithin to check which points fall within that area:

declare @kmlarea geography

select @kmlarea = geography::EnvelopeAggregate(geography::Point(Lat, Long, 4326))
from kmldata

select *
from address_points a
where geography::Point(Latitude1, Longitude2, 4326).STWithin(@kmlarea) = 1

There are several ways of calculating the geographical distance between two sets of coordinates. Already posted is the built in Geography method. There are also several good "home grown" functions based on a round earth model.

The hard part is making the actual comparison when you have large row counts in your source and destination tables. Comparing every source to every destination creates an unnecessarily large Cartesian product. I say "unnecessarily" because there's no point in calculating the distance between a source in Florida and a destination in California when I'm only interested in destinations withing 15 miles of the source.

To solve the problem, I created a "bounding box" function that calculates a square(ish) box around a single set of coordinates. The code is posted below...

CREATE FUNCTION dbo.tfn_LatLngBoundingBox
/* ===================================================================
12/03/2019 JL, Created: Calculates the bounding box for a given set of Lat/Lng coordinates.
=================================================================== */
--===== Define I/O parameters
(
    @Lat DECIMAL(8,5),
    @Lng DECIMAL(8,5),
    @MaxDistance DECIMAL(8,3),
    @DistanceUnit CHAR(1)       -- 'M'=miles ; 'K'=kilometers
)
RETURNS TABLE WITH SCHEMABINDING AS
RETURN
    SELECT 
        MinLat = CONVERT(decimal(8, 5), (x.MinLat / PI()) * 180),
        MaxLat = CONVERT(decimal(8, 5), (x.MaxLat / PI()) * 180),
        MinLng = CONVERT(decimal(8, 5), (y.MinLng / PI()) * 180),
        MaxLng = CONVERT(decimal(8, 5), (y.MaxLng / PI()) * 180)
    FROM
        ( VALUES (
                CASE 
                    WHEN @DistanceUnit = 'K' THEN @MaxDistance / 6366.707019    -- Earth sphere radius in kilometers
                    WHEN @DistanceUnit = 'M' THEN (@MaxDistance * 1.609344) / 6366.707019
                END,
                (@Lat / 180) * PI(), 
                (@Lng / 180) * PI()
                ) ) r (DistRad, rLat, rLng)
        CROSS APPLY ( VALUES (r.rLat - r.DistRad, r.rLat + r.DistRad) ) x (MinLat, MaxLat)
        CROSS APPLY ( VALUES (ASIN(SIN(r.rLat) / COS(r.DistRad))) ) lt (LatT)       -- = 1.4942 rad
        CROSS APPLY ( VALUES (ACOS( ( COS(r.DistRad) - sin(lt.LatT) * sin(r.rLat) ) / ( cos(lt.LatT) * cos(r.rLat) ) ) ) ) dl (DeltaLng)
        CROSS APPLY ( VALUES (r.rLng - dl.DeltaLng, r.rLng + dl.DeltaLng) ) y (MinLng, MaxLng);
GO

The use case looks like the following...

SELECT
    s.Lat,
    s.Lng,
    d.Lat, 
    d.Lng,
    dm.DistanceInMiles  
FROM
    dbo.[Source] s
    CROSS APPLY dbo.tfn_LatLngBoundingBox(s.Lat, s.Lng, 15, 'M') bb
     LEFT JOIN dbo.Destination d
        ON d.lat BETWEEN bb.MinLat AND bb.MaxLat
        AND d.Lng BETWEEN bb.MinLng AND bb.MaxLng
    CROSS APPLY dbo.tfn_LatLonDistanceInMiles(s.Lat, s.Lng, d.Lat, d.Lng) dm    
WHERE 
    dm.DistanceInMiles <= 15;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM