I have table 1 that has North, South, East and West coordinates for a specific region.
On each record in table 2, I have Latitude and Longitude coordinates. How do I write a query to see if these coordinates are in the designated range specified in table 1
Table 1:
MapNorthLat MapSouthLat MapEastLong MapWestLong
36.912220 33.738137 -76.189200 -82.380500
Table 2
_Geo_Lat _Geo_Lon
34.23184 -77.929218
Not having any luck with the logic of this code
Related
How should I write query for this? Consider P1(a, b) and P2(c, d) to be two points on a 2D plane.
a happens to equal the minimum value in Northern Latitude (LAT_N in STATION)
b happens to equal the maximum value in Northern Latitude (LAT_N in STATION)
c happens to equal the minimum value in Western Longitude (LONG_W in STATION)
d happens to equal the maximum value in Western Longitude (LONG_W in STATION)
Query the Manhattan Distance/Eculids Distance between points P1 and P2 and round it to a scale of 4 decimal places.
Table STATION(ID number, CITY varchar2(21), STATE varchar2(2), LAT_N number, LONG_W number)
any idea will be appreciated
SELECT
CAST(ABS(MAX(LAT_N) - MIN(LAT_N))
+ ABS(MAX(LONG_W) - MIN(LONG_W))as numeric(32,4))
FROM
STATION;
Easiest way of doing this problem is
Using mathematics function [ Dis. = sqrt((x2−x1)^2+(y2−y1)^2) ], try:
for sql server:
for Manhattan Distance:
select format(abs(min(LAT_N)-max(LAT_N))+abs(min(long_w)-max(long_w)),'.####') from station;
And for Eculids Distance:
select format(sqrt(square(min(LAT_N)-max(LAT_N))+square(min(long_w)-max(long_w))),'.####') from station;
everyone, I have table name 'geom' and I would like to calculate the distance between points that exist in my table like 0101000020730800001DAB949EE95D4040E124CD1FD3F04340
and entry points longitude and latitude and I tried this
SELECT *
FROM postgis.cafeecoor
WHERE ST_Distance_Sphere(geom, ST_MakePoint(32.733792,39.865589)) <= 1 * 1609.34
You can use the geography datatype that returns distances in meters.
SELECT *, st_distance(geom::geography, ST_MakePoint(32.733792,39.865589)::geography)
FROM postgis.cafeecoor
For your example, it returns 1760.32533367 meters.
Depending how your geometry is saved (as a true geometry or as text, with or without a set projection), you might have to add a few extra steps, like creating the geometry and setting its coordinate system
SELECT *, st_distance(
st_setsrid(geom::geometry,4326)::geography,
ST_MakePoint(32.733792,39.865589)::geography)
FROM postgis.cafeecoor;
I used ST_Distance_Spheroid in PostgreSQL (with Postgis) to calculate the distance between Woking and Edinburgh like as follows:
CREATE TABLE pointsTable (
id serial NOT NULL,
name varchar(255) NOT NULL,
location Point NOT NULL,
PRIMARY KEY (id)
);
INSERT INTO pointsTable (name, location) VALUES
( 'Woking', '(51.3168, -0.56)' ),
( 'Edinburgh', '(55.9533, -3.1883)' );
SELECT ST_Distance_Spheroid(geometry(a.location), geometry(b.location), 'SPHEROID["WGS 84",6378137,298.257223563]')
FROM pointsTable a, pointsTable b
WHERE a.id=1 AND b.id=2;
I got a result of 592km (592,053.100454442 meters).
Unfortunately, when I used various sources on the web to make the same calculation I consistently got around the 543km mark which is different by 8.2%.
source 1 - 338 miles (543.958 km)
source 2 - 544.410km
source 3 - 543.8km
Luckily, the third source clarified that they were using the haversine formula. I am not sure about the other two sources.
Did I do something wrong in my queries or is this down to a difference in the formulas used? If so, which calculation is closest to the shortest distance a crow could fly, keeping a constant elevation?
You swapped the latitude and the longitude. If you put them in the right order you would get 544 430m. The distance computation is using the great circle arcs, which is the true shortest distance between points over a sphere.
WITH src AS (
select st_geomfromtext('POINT(-0.56 51.3168)',4326) pt1,
st_geomfromtext('POINT(-3.1883 55.9533)',4326) pt2)
SELECT
ST_DistanceSpheroid(pt1, pt2, 'SPHEROID["WGS 84",6378137,298.257223563]') Dist_sphere,
ST_Distance(pt1::geography, pt2::geography) Dist_great_circle
FROM src;
dist_sphere | dist_great_circle
------------------+-------------------
544430.941199621 | 544430.94119962
(1 row)
On a side note, there is a warning
ST_Distance_Spheroid signature was deprecated in 2.2.0. Please use
ST_DistanceSpheroid
Given the following data, would it be possible, and if so which would be the most efficient method of determining whether the location 'Shurdington' in the first table is contained within the given radius's of any of the locations in the second table.
The GeoData column is of the 'geography' type, so using SQL Servers spatial features are 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 assistance is greatly apprecieded.
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 a POINT
DECLARE #p GEOGRAPHY = GEOGRAPHY::STGeomFromText('POINT(-2.113189 51.8677979)', 4326);
To find out if it is in 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 it all into a single 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: Efficiency. With some correct indexing it appears SQL's spatial indexes can be very quick
If you want to do the maths yourself, you could use Equirectangular approximation based upon Pythagoras. The formula is:
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 give those locations in your 2nd table that contain your entry in the 1st within their 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 is likely good enough. If you are looking at distances that stretch across the globe you may wish to Google 'haversine' formula.
It may be worth comparing this with Paddy's solution to see how well they agree and which performs best.
You calculate the distance between the two points and compare this distance to the given radius.
For calculating short distances, you can use the formula at Wikipedia - Geographical distance - Spherical Earth projected to a plane, which claims to be "very fast and produces fairly accurate result for small distances".
According to the formula, you need the difference in latitudes and longitudes and the mean latitude
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
I used the with selects as intermediate steps to keep the calculations "readable".
How can i control the latitude and the longitude of the Team and the Customer with reasonable error margin from the Job Table?
if the two values are close to eachother i will return it "true", if not "false"
Job Table (like this) :
JobID CustomerID TeamID
2 13 1
3 13 2
Team Table :
TeamID Latitude Longitude
1 41.019 28.965
2 42.019 27.165
Customer Table
ID Latitude Longitude
13 13.557 13.667
The function:
CREATE FUNCTION dbo.DictanceKM(#lat1 FLOAT, #lat2 FLOAT, #lon1 FLOAT, #lon2 FLOAT)
RETURNS FLOAT
AS
BEGIN
RETURN ACOS(SIN(PI()*#lat1/180.0)*SIN(PI()*#lat2/180.0)+COS(PI()*#lat1/180.0)*COS(PI()*#lat2/180.0)*COS(PI()*#lon2/180.0-PI()*#lon1/180.0))*6371
END
i assume you mean: how can i write a select statement to return true if two latitudes and longitudes are within x miles of each other... or something like that?
look up 'great_circle_distance'
write a query that links the customer to the team.
perform the great circle distance calculation on the two lats and longs.
compare this to you desired distance.
use decode or some similar construct to turn that into a 'True' or 'False' value.
SQL has a geography datatype and a method to calculate the distance between two. Covert your Lat, Long pairs to geography.
http://msdn.microsoft.com/en-us/library/microsoft.sqlserver.types.sqlgeography.stdistance.aspx
Then you could use a function to return a true or false.