Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Finding a geography point within a range of another - SQL Server

I have a table in SQL Server that has geography datatype column in it. I want to query this table to find rows that fall near (within a range) of another given geography point. Does anyone have any ideas as to the best way to do this? I have 2 options of where to do this type of query. I can write it on the sql server as a stored proc or I can do it in c# code as I am using the Entity Framework for data access.

I would have a query that has a range (eg 100m) and a geography point passed in to it. The pseudo code would be something like this...

select rows where rows.geo within range of given geography point

I'm having a bit of trouble finding examples of geography queries in SQL Server on the web.

Any help would be appreciated.

like image 857
Ben Cameron Avatar asked Dec 05 '11 11:12

Ben Cameron


People also ask

How do you use range value in SQL?

The SQL BETWEEN OperatorThe BETWEEN operator selects values within a given range. The values can be numbers, text, or dates. The BETWEEN operator is inclusive: begin and end values are included.

How do I find a range in SQL?

The SQL Between operator is used to test whether an expression is within a range of values. This operator is inclusive, so it includes the start and end values of the range. The values can be of textual, numeric type, or dates. This operator can be used with SELECT, INSERT, UPDATE, and DELETE command.

What is geography in SQL Server?

The geography spatial data type, geography, is implemented as a . NET common language runtime (CLR) data type in SQL Server. This type represents data in a round-earth coordinate system. The SQL Server geography data type stores ellipsoidal (round-earth) data, such as GPS latitude and longitude coordinates.

What is Range function in SQL?

The RANGE function returns the range of values for a numeric column expression argument. It calculates the difference between the maximum and the minimum values, as follows: range(expr) = max(expr) - min(expr); You can apply the RANGE function only to numeric columns.


2 Answers

You are already using SQL Server Spatial and geography columns, so you can just use the following to get the result. There are two ways:

Using STDistance():

-- Get the center point
DECLARE @g geography
SELECT @g = geo FROM yourTable WHERE PointId = something

-- Get the results, radius 100m
SELECT * FROM yourTable WHERE @g.STDistance(geo) <= 100

Using STBuffer() and STIntersects

-- Get the center buffer, 100m radius
DECLARE @g geography
SELECT @g = geo.STBuffer(100) FROM yourTable WHERE PointId = something

-- Get the results within the buffer
SELECT * FROM yourTable WHERE @g.STIntersects(geo) = 1

From my experience the performance of two methods varies with data distribution and spatial index grid size, so test on your own data to decide which one to use. Remember to have Spatial Index created on the geo column.

like image 84
Alan Avatar answered Oct 04 '22 22:10

Alan


Assuming you have lat and long values of the points in the db.

select * from yourtable where SQRT 
( POWER((yourtable.lat - reflat) * COS(reflat/180) * 40000 / 360, 2) 
+ POWER((yourtable.long - reflong) * 40000 / 360, 2)) < radiusofinterest

reflat and reflong is the point from which you want to know the places close to. radiusofinterest is the distance from this point. 40000 is the circumference of the earth. you could use more accurate figures.

i havent checked the syntax with SQLServer though.... so there may be some errors there.

the cos(reflat) corrects the circumference based on the lat you are in. It should work ok for smaller distances.

like image 44
Sid Malani Avatar answered Oct 04 '22 21:10

Sid Malani