I have 2 points containing Lattitude and Longitude Coordinates. I'd like to figure out how to find the zipcodes within this set of Points. I have a query which provides me with a set of zipcodes based on a central lattitude and longitude point extending X miles in radius, but that isn't precisely what I am looking for. What I am looking for is to extract the zipcodes within two points.
So, for example:
Coordinate A = 28.37,-81.5568 (Orlando, Florida)
Coordinate B = 25.6132,-80.3474 (Miami, Florida)
Here is my query to extract all locations from my database based on a central point (In this case I am using Orlando, FL:
$sql="SELECT zip_code_id, (
3959 * ACOS (
COS ( RADIANS(28.37) )
* COS( RADIANS( lat ) )
* COS( RADIANS( lon ) - RADIANS(-81.5568) )
+ SIN ( RADIANS(28.37) )
* SIN( RADIANS( lat )
))) AS distance FROM zip_code HAVING distance < 30 ORDER BY distance LIMIT 0 , 20;";
What I am trying to determine is the zipcodes within Orlando to Miami based on these two points.
Thanks!
You need to get points between the two coordinates - maybe using the Haversine formula and then collect the zipcodes for the points along the line.
Related
I want to find a place (longitude and latitude) with distance less than 10 km from a known longitude and latitude using BigQuery SQL. Is there any possible query for this?
I read your request as saying that given a geospatial point, you wish to query for anything within less than a 10km radius of that point. Here's two ways to solve this:
Using ST_BUFFER
You could use the ST_BUFFER function which similarly takes an argument of the radius to use around a point, but instead uses a segmented circle with 8 segments by default.
SELECT *
FROM `table`
WHERE ST_CONTAINS(
ST_BUFFER(
ST_GEOPOINT(longitude, latitude),
10 * 1000), -- Radius argument is expressed in meters
YourGeoPointColumn)
Using ST_BUFFERWITHTOLERANCE
You might use ST_BUFFERWITHTOLERANCE that replaces the segmented circle with tolerance instead of circle segments.
SELECT *
FROM `table`
WHERE ST_CONTAINS(
ST_BUFFERWITHTOLERANCE(
ST_GEOPOINT(longitude, latitude),
10 * 1000, -- Radius argument is expressed in meters
1), -- Tolerance of 1% of the buffer radius, expressed in meters
YourGeoPointColumn)
ST_Distance function should work here, like this:
with data as (
select 1 id, st_geogpoint(-122, 47) as geo
union all
select 2 id, st_geogpoint(-121, 47) as geo
)
select * from data
where st_distance(geo, st_geogpoint(-122.1, 47)) < 10000
id geo
------------------
1 POINT(-122 47)
Another way to write the distance condition is
ST_DWithin(geo, st_geogpoint(-122.1, 47), 10000)
If something does not work, please provide sample data and what data you expect in the results but is missing.
I have a web site the I have created to sell items locally which if free for everyone to use. But I have now come accross a little problem! Now people form further afield are joining I want them to be able to search and lit all items by distance from them and/or see all items in their area.
I have been collecting everyones postcode and converting them to Easting and Northing coords not Latitude-longitude.
Is the best way to create a new recodset on the fly do the distance calc then sort by distance or is there a better way that will use less resources on the site?
Here is the answer
strSQL = "SELECT *, ( 3959 * acos( cos( radians( " & strMyLat &
") ) * cos( radians(Latitude) ) * cos( radians(Longitude) - radians(" & strMyLng &
") ) + sin( radians( " & strMyLat &
") ) * sin( radians(Latitude) ) ) ) AS distance FROM TABLE WHERE HAVING distance < 3;" '## 3 Miles
To answer your question:
I did almost the same thing last year, but with lat/long. And had the distances calculated real time. The distances are calculated using strait math, so it's fast and not a lot of resources are used.
Not familiar with Easting and Northing coords, so it may, or may not, be faster to first permanently convert them to lat/long in your DB, or some other coordinate system.
Now, if you're determined to make the query go as fast as possible, and you're dealing with a very small list of postal codes, you can create a lookup table that has the distance between any 2 postal codes already calculated.
However the larger your list, the more this becomes unwieldy. For example, according to Wikipedia, there are about 1,700,000 postal codes in the UK, so such a table would need the square of that, or 2,890,000,000,000 records.
Good Luck!
P.s. Here's the formula for finding the distance between 2 Easting/Northing coords:
d = squareroot(square(E1-E2)+square(N1-N2))/1000
The 1000 is assuming your coords are in meters and you want the answer in km. Otherwise, adjust this number accordingly.
Bit Late to the party, but UK Eastings/Northings are just a 1km by 1km grid overlaid on the country, so the maths to get the distance between two points is just Pythagoras theorem where you want to get the hypotenuse from the other two sides.
Following pseudocode shows the maths:
DeltaX = X1-X2 --the length of side 1
DeltaY = Y1-Y2 --the length of side 2
Hypotenuse = SQRT(DeltaX^2 + DeltaY^2)
Easting and northing is not the way to go.
You must first convert the coordinates (whatever they are like Easting , Northing, etc)
to latitude, longitude decimal degrees WGS84.
This is the cooridnate system that the whole world uses, and now you can start calculation:
Then simply calculate the distance between two lat,lon pairs, e.g with the haversine-Distance formula (see Google, or Wiki).
I know there are many threads about calculating from lat/long to metric systems. This solves the first part of my problem.
The second (main part) of my problem is this:
I have google maps as map app.
I have a lat&long pair of a point
I have a a metric distance, lets say 30meters.
I need some point to do a sql query.
Why?
I have many records of POIs which can be located with this lat&long pair. I don't want to get all the results (reason: better performance).
Is there a way to do something like:
select * from myTable where lat> .... and lat < ... and long > ... and long < ...?
Is this possible? And if its, how do I get these values in ... ?
Regards!
Take a look at the article: Selecting points within a bounding circle
and the SO question: SQL Query for Performing Radius Search based on Latitude Longitude
These should get you started.
here is a sample query that returns the distances between a supplier lat/lng and a database of lat/lng pairs:
DECLARE
#Latitude float,
#Longitude float
SET #Latitude = 46.51257000000000
SET #Longitude = -84.33660900000000
DECLARE #SampleData TABLE
(
Name varchar(100),
Lat float,
Lng float
)
INSERT INTO #SampleData
(Name, Lat, Lng)
SELECT 'Point1', 46.52450048415351,-84.35223018530274
UNION
SELECT 'Point2', 46.51835838382206,-84.30279170874024
UNION
SELECT 'Point3', 46.522138220045285,-84.2622796237793
UNION
SELECT 'Point4', 46.54056115608927,-84.223140829834
SELECT
Name,
Lat,
Lng,
-- using spherical law of cosines, where 6371 is the earth's radius in km. Returns km.
Distance = ACOS(SIN(RADIANS(#Latitude))*SIN(RADIANS(Lat))+COS(RADIANS(#Latitude))*COS(RADIANS(Lat))*COS(RADIANS(Lng-#Longitude)))*6371
FROM
#SampleData
I have a database of coordinates in the schema:
ID:Latitude:Longitude:name:desc
I've set up my google maps application to show the markers effectively on the screen. However I need to add another feature whereby the user can view all pointers that fall within the radius from a central point.
How would I write up a sql statement of the kind:
Select all pointers that fall within a 10 mile radius of X & Y
The SQL below should work:
SELECT * FROM Table1 a
WHERE (
acos(sin(a.Latitude * 0.0175) * sin(YOUR_LATITUDE_X * 0.0175)
+ cos(a.Latitude * 0.0175) * cos(YOUR_LATITUDE_X * 0.0175) *
cos((YOUR_LONGITUDE_Y * 0.0175) - (a.Longitude * 0.0175))
) * 3959 <= YOUR_RADIUS_INMILES
)
This is based on the spherical law of cosines, for more detailed information on the topic, check out this article - http://www.movable-type.co.uk/scripts/latlong.html
You probably need to do this in two steps. Select the points that lie within a 20 mile square with it's centre at X,Y. Assuming you calculate the top,left and bottom,right coordinates of the square first you can get all the points inside the square from the database with:
select * from coordinates where longitude < right and longitude > left and
latitude < top and latitude > bottom;
The second step is to see whether the set of points is inside the 10 mile radius circle. At this point I would be tempted to use Google maps to calculate the distance between the points and the centre of your square using the google.maps.geometry.spherical.computeDistanceBetween(from:LatLng, to:LatLng, radius?:number)function. Check the answer is less than 10 miles. This function uses the radius of the earth as a default.
This SQL gives more accurate answer:
SELECT *
FROM Table1 a
WHERE 1 = 1
AND 2 * 3961 * asin(sqrt( power((sin(radians((X - cast(a.latitude as decimal(10,8))) / 2))) , 2) + cast(cos(radians(cast(a.latitude as decimal(18,8)))) * cos(radians(X)) * power((sin(radians((Y - cast(a.long as decimal(18,8))) / 2))) , 2) as decimal(18,10) ))) <= Radius_In_Miles
X = Latitude of Centroid
Y = Longitude of Centroid
I did it in Redshift, so I had to use cast to prevent numeric value overflow error.
Reference: http://daynebatten.com/2015/09/latitude-longitude-distance-sql/
Before I embark on a a pretty decent overhaul of my web app to use a spatial query, I'd like to know if this MySQL query works in SQL Server 2008:
SELECT id, ( 3959 * acos( cos( radians(37) ) * cos( radians( lat ) ) *
cos( radians( lng ) - radians(-122) ) + sin( radians(37) ) *
sin( radians( lat ) ) ) ) AS distance
FROM markers HAVING distance < 25
ORDER BY distance LIMIT 0 , 20;
Or is there a better way to do this in SQL Server 2008?
My database currently stores that lat/long of businesses near military bases in Japan. However, I'm querying the table to find businesses that contain the specified bases' id.
Biz table
----------------------
PK BizId bigint (auto increment)
Name
Address
Lat
Long
**FK BaseId int (from the MilBase table)**
A spatial query, based on having a center lat/long and given radius (in km) would be a better fit for the app and would open up some new possibilities.
Any help is greatly appreciated!
It looks like you're selecting the distance between two points. In SQL Server 2008, you can use the STDistance method of the geography data type. This will look something like this:
SELECT TOP 20
geography::STGeomFromText('POINT(-122.0 37.0)', 4326).STDistance(p)
FROM markers
WHERE geography::STGeomFromText('POINT(-122.0 37.0)', 4326).STDistance(p) < 25
ORDER BY geography::STGeomFromText('POINT(-122.0 37.0)', 4326).STDistance(p);
Where p would be a field of type geography instead of two separate decimal fields. You may probably also want to create a spatial index on your p field for better performance.
To use the geography data type, simply specify your field as geography in your CREATE TABLE:
CREATE TABLE markers (
id int IDENTITY (1,1),
p geography,
title varchar(100)
);
Inserting values into your markers table will now look like this:
INSERT INTO markers (id, p, title)
VALUES (
1,
geography::STGeomFromText('POINT(-122.0 37.0)', 4326),
'My Marker'
);
Where -122.0 is the longitude, and 37.0 is the latitude.
Creating a spatial index would look something like this:
CREATE SPATIAL INDEX ix_sp_markers
ON markers(p)
USING GEOGRAPHY_GRID
WITH ( GRIDS = (HIGH, HIGH, HIGH, HIGH),
CELLS_PER_OBJECT = 2,
PAD_INDEX = ON);
If you are only interested in retrieving points within 25 miles, then there is absolutely no need to use spherical or great circle math in the distance calculations... More than sufficient would be to just use the standard cartesian distance formula...
Where Square(Delta-X) + Square(Delta-Y) < 225
All you need to do is convert the difference in Latitudes and the difference in longitudes to mileages in whatever units you are using (statue miles naultical miles, whatever)
If u r using nautical miles each degree of latitude = 60 nm...
And each degree of Longitude is equal to 60 * cos(Latitude) nm
Here if both points are within 25 miles of one another, you don;t even need to worry about the difference between this factor from one point to the other...