Is a point within a geographic radius - SQL Server 2008

Given the following data, it would be possible, and if it were the most effective method for determining whether the location of the "Shurdington" in the first table is within a given radius of any of the places in the second table.

The GeoData column is of the geography type, so using SQL Server spatial functions is an option, as well as using latitude and longitude.

Location      GeoData       Latitude    Longitude
===========================================================
Shurdington   XXXXXXXXXX    51.8677979  -2.113189

ID  Location            GeoData     Latitude    Longitude   Radius
==============================================================================
1000    Gloucester      XXXXXXXXXX  51.8907127  -2.274598   10
1001    Leafield        XXXXXXXXXX  51.8360519  -1.537438   10
1002    Wotherton       XXXXXXXXXX  52.5975151  -3.061798   5
1004    Nether Langwith XXXXXXXXXX  53.2275276  -1.212108   20
1005    Bromley         XXXXXXXXXX  51.4152069  0.0292294   10

Any help is greatly appreciated.

+6
source share
3 answers

Create data

CREATE TABLE #Data (
    Id int,
    Location nvarchar(50),
    Latitude decimal(10,5),
    Longitude decimal(10,5),
    Radius int
)

INSERT #Data (Id,Location,Latitude,Longitude,Radius) VALUES 
(1000,'Gloucester', 51.8907127 ,-2.274598  , 20), -- Increased to 20
(1001,'Leafield', 51.8360519 , -1.537438  , 10),
(1002,'Wotherton', 52.5975151,  -3.061798  , 5),
(1004,'Nether Langwith', 53.2275276 , -1.212108  , 20),
(1005,'Bromley', 51.4152069 , 0.0292294  , 10)

Test

Declare your point of interest as POINT

DECLARE @p GEOGRAPHY = GEOGRAPHY::STGeomFromText('POINT(-2.113189 51.8677979)', 4326);

To find out if it is within the radius of another point:

-- First create a Point.
DECLARE @point GEOGRAPHY = GEOGRAPHY::STGeomFromText('POINT(-2.27460 51.89071)', 4326);
-- Buffer the point (meters) and check if the 1st point intersects
SELECT @point.STBuffer(50000).STIntersects(@p)

Combining all this into one query:

select  *,
        GEOGRAPHY::STGeomFromText('POINT('+ 
            convert(nvarchar(20), Longitude)+' '+
            convert( nvarchar(20), Latitude)+')', 4326)
        .STBuffer(Radius * 1000).STIntersects(@p) as [Intersects]
from    #Data  

gives:

Id      Location        Latitude    Longitude   Radius  Intersects
1000    Gloucester      51.89071    -2.27460    20      1
1001    Leafield        51.83605    -1.53744    10      0
1002    Wotherton       52.59752    -3.06180    5       0
1004    Nether Langwith 53.22753    -1.21211    20      0
1005    Bromley         51.41521    0.02923     10      0

Re: . , SQL

+9

.

- - , , , " ".

​​ ​​

with geo as (select g1.id, g1.latitude as lat1, g1.longitude as long1, g1.radius,
                    g2.latitude as lat2, g2.longitude as long2
             from geography g1
             join geography g2 on g2.location = 'shurdington'
                               and g1.location <> 'shurdington')
     base as (select id,
                     (radians(lat1) - radians(lat2)) as dlat,
                     (radians(long1) - radians(long2)) as dlong,
                     (radians(lat1) + radians(lat2)) / 2 as mlat, radius
              from geo)
     dist as (select id,
                     6371.009 * sqrt(square(dlat) + square(cos(mlat) * dlong)) as distance,
                     radius
              from base)
select id, distance
from dist
where distance <= radius

with select , "" .

+1

, Equirectangular Pythagoras. :

var x = (lon2-lon1) * Math.cos((lat1 + lat2)/2); var y = (lat2-lat1); var d = Math.sqrt(x * x + y * y) * R;

In terms of SQL, this should indicate the places in your 2nd table that contain your record in the 1st radius:

SELECT *
FROM Table2 t2
WHERE EXISTS (
 SELECT 1 FROM Table1 t1
 WHERE 
  ABS (
  SQRT (
    (SQUARE((RADIANS(t2.longitude) - RADIANS(t1.longitude)) * COS((RADIANS(t2.Latitude) + RADIANS(t1.Latitude))/2))) +
    (SQUARE(RADIANS(t1.Latitude) - RADIANS(t2.Latitude)))
    ) * 6371 --Earth radius in km, use 3959 for miles
    )
    <= t2.Radius
)

Note that this is not the most accurate method available, but most likely it is good enough. If you look at distances that extend all over the world, you might want the Google haversine formulas.

It might be worth comparing this with Paddy's solution to see how much they agree and what works best.

+1
source

All Articles