My query is
SELECT A.broker_property_id, A.broker_owner_id
FROM property_requirement_new AS A,
(SELECT X(latlong), Y(latlong)
FROM client_property_new
WHERE property_id = 132) AS B
WHERE (POW((A.X(latlong)-B.X(latlong))*111.12, 2) + POW((A.Y(latlong) - B.Y(latlong))*111.12, 2)) <= 4
Here, latlong is a field of mysql's POINT datatype.
But this query is not being executed and is showing the following error:
FUNCTION a.X does not exist
Can anyone help me out with the correct method to do it or to spot the error in my code?
X and Y are functions that take a Point (geometry) as an input. It is not a function of table A, as you have written it, ie, A.X(latlong) is throwing an error as it implies that X is a function of table A.
You would need to write
select X(latlon), Y(latlon) from A
or in your case, if you are using subqueries:
select X(A.latlon), Y(A.latlong) from (.....) A
There is apparently an ST_Distance function in MySQL 5.6, but I have never used it and it seems somewhat undocumented.
There is some discussion of distance functions in MySQL here: Fastest Way to Find Distance Between Two Lat/Long Points One of the general problems of spatial in MySQL is that it does not support projections properly, so you are either left doing Pythagoras on planar coordinates, or implementing some version of the haversine formula and assuming the world is a sphere -- which will work well for short distances if massive precision is not your biggest concern.
Related
I see many solutions for getting the nearest rows from a POINT to convert to X() and Y() and do trig calculations of distances... As I understand, this does not seem to take advantage of the spatial index?
How do you take advantage of the spatial index, in the most common sense of, returning rows whose spatial POINT is within a radius from a center POINT?
In other words, how do you get something like this - where LatLng is the lat lng location stored as POINT for each row, and CenterPoint the epicenter
Pseudocode query: SELECT * FROM geotable WHERE d=Distance(LatLng,CenterPoint) < 10 ORDER by d
You can use st_distance_sphere
SELECT *
FROM geotable
WHERE st_distance_sphere(POINT(-82.337036, 29.645095 ), POINT(`longitude`, `latitude` ))/1000 < 10
Here you can see a working example
MYSQL ver 5.7
Requirement:
I have a bunch of POINT geometries in MYSQL table and I have to find all the POINT geometries that are within 5km distance/radius of a GEOMETRYCOLLECTION object.
GEOMETRYCOLLECTION may contain more than one type of geometries like POINT, POLYGON etc.
Sample GEOMETRYCOLLECTION data:
SET #g1 = ST_GeomFromText('GEOMETRYCOLLECTION(POINT (-156.366489591715 66.913750389327),POLYGON ((-156.357608905242 66.906958164897, -156.360302383363 66.9066027336476, -156.361997104194 66.9067073607308, -156.363616093774 66.9066368440642, -156.365477697938 66.9065867326059, -156.368127298976 66.9065970034393, -156.370061891681 66.9066888794808, -156.37182258022 66.9068547305222, -156.373286981259 66.9070724523969, -156.374390675008 66.9072952721882, -156.376359777088 66.9077681138541, -156.377706173961 66.9080113180204, -156.379222192708 66.9081328753119, -156.380729601039 66.9081591586452, -156.382562289578 66.9081211961453, -156.387571662487 66.9099676951007, -156.389320598943 66.9125180930134, -156.389291120818 66.9145787836353, -156.384722634367 66.9167899596735, -156.37955035 66.9195246586276, -156.372520662511 66.9209119638337, -156.360432280238 66.9215118034161, -156.355776993787 66.9203754471679, -156.34906598338 66.9180659711298, -156.347941981299 66.9174007836309, -156.346853913592 66.9167568252985, -156.34605399901 66.9158971169665, -156.346982815675 66.9151925950926, -156.346794497967 66.9144321773854, -156.345642955261 66.9140107294695, -156.343831364638 66.9136152003034, -156.342996512556 66.9130307378043, -156.343113243806 66.9123137492637, -156.343498096931 66.9119029992644, -156.344661664637 66.9111819440571, -156.345080786511 66.9105884961414, -156.345524286511 66.9099605023924, -156.347168040675 66.9098486503092, -156.348952756297 66.9096090419763, -156.348689200048 66.9089614565606, -156.349495732338 66.908706844061, -156.350786711503 66.9082992794783, -156.352211271917 66.9083472388533, -156.353952768789 66.90829894302, -156.355389368787 66.9082072242701, -156.356512531285 66.9079768284371, -156.356677961493 66.9078075857291, -156.356422527119 66.907644261771, -156.355901372953 66.9072802273965, -156.357608905242 66.906958164897)))');
Sample POINT data:
SET #p1 = ST_GeomFromText('GEOMETRYCOLLECTION(POINT (-156.342840017 66.9320439348))');
I have tried ST_DISTANCE_SPHERE(#g1,#p1) spatial function (which returns the value in meters) but it seems it doesn't support geometry types other than POINT and MULTIPOINT.
Then I have used:
ST_DISTANCE(#g1,#p1)
'0.015301834064271899'
I am unable to understand the what is the UNIT of this returned value in MYSQL 5.7?
I have searched a lot on the internet and there is no proper documentation available regarding the same. In POSTGIS, this can be done but I am struggling to do this in MYSQL ver 5.7.
Any help is appreciated.
Thanks in advance!
ST_Distance returns "distance" in degrees here - i.e. the flat map view of the shortest distance between shapes. This value cannot be mapped to real distance, as real world distance of 1 degree along parallel is different from distance of 1 degree along meridian except near the equator.
Looks like MySQL cannot correctly compute distance here. You would be better served by systems with more geospatial support, like PostgreSQL + PostGIS, or Google BigQuery, etc. They give you correct answer, you just need to replace ST_GeomFromText with ST_GeogFromText to work with spherical geographies.
I try searching for this problem on the web, but to no avail. Seems like a basic task. I'm using PostGresql through SQLAlchemy with Geoalchemy to do geospatial queries. Technically, I'm using `Flask-SQLAlchemy. I can do a geospatial query. For example:
from geoalchemy2 import func
cls.db.session.query(cls).filter(func.ST_DWithin(cls.geoLoc, geo, meters))
where cls is the class I'm querying on. geo is the Geography point representing the center of the query and meters is the max distance to return results from. This query works, but returns results in an arbitrary order. I want them returned in increasing (decreasing is fine too) distance from the query point.
I assume I need to use an .order_by(...) at the end of the query, but I can't figure out what to put in there.
Alright, I figured it out, but wow that wasn't obvious, especially if you're not intimately familiar with Geoalchemy2.
In my case above, you have to tack:
.order_by(func.ST_Distance(cls.geoLoc, geo))
to the end of the code that's in my question. Basically, ST_Distance is a function that takes in a two points and returns the distance between them. So cls.geoLoc refers to the each object in question from the table and geo is the center from which I'm sorting by distance. This basically computes the distance for each element to geo and then sorts by it.
I have the following latitude and longitude:
lat - 18.9802767
lng - 72.8142511
I am trying the following query for places withint 10 kms from the point of interest.
select mbrcontains( geomfromtext(
'LINESTRING(72.8993663648088 19.0702857,72.72913583519122 18.8902677)'
),
geomfromtext(
'point(18.9802767 72.8142511)'
) );
The Linestring geometry object is derived from the exact point that I am trying to determine is within using the method for mysql 5.1 and above from this example using the formula :
linestring(point(#lng+10/(111.1/cos(radians(#lat))),#lat+10/111.1), point(#lng-10/(111.1/cos(radians(#lat))),#lat-10/111.1))
From what I understand the point falls within the Minimum Bounding Rectangle (MBR). However the query returns a 0 for the answer. The above is following the principles given in this example.
What is wrong with the query? How can I know if the point is within a certain geospatial distance (in this case the MBR points are calculated using 10 kms from the point given by co-ordinates: lat - 18.9802767, lng - 72.8142511).
BTW, I am using MySQL 5.5.32.
Your point does not fall within the MBR of the line. Looks like you've reversed the latitude or longitude coordinates on either the line or the point. Switch the X and Y in 'point(18.9802767 72.8142511)' to get this point, which will be within the MBR of the line:
POINT (72.8142511 18.9802767)
If you are tied to MySQL, you may consider updating to MySQL 5.6, then using the Buffer function to create a circular area from your point of interest, and then use ST_Within to find anything within that circular area.
If you are not tied to MySQL, consider PostGIS, which provides a nice ST_DWithin function that makes these comparisons very easy.
I have to discover if a given point is at least 500 meters (ou other distance) from a route line that exist in my database recorded using the MySQL Spatial.
I see there is no similar function in MySQL Spatial, and find a previous answer that doesn't work for me because the line is too big (more than 300km) to check with this solution point by point:
Find N Nearest LineString From A Point Using MySQL Spatial Extensions
I'm even can't create a buffer (a circle/polygon with a given radius) to the point to check if is even touch.
UPDATE - 12/7
I did it, but MySQL Spatial it is seams not trustable.
I made a createBuffer function, to create a 20 points Polygon around the given Point with a meters given distance for the radius: http://pastebin.com/xEFb8ZXi
I'm testing with the QGis the given results from this buffer, and everything is fine with the function (except the meters to decimal degress value that generate smaller then expected, but it is not the issue right now).
And made a few Intersects checks, and this is aways return true, even if the result polygon is not intersects the line.
I remade the same tests using just the center point, and the results is the same.
I discovery now that the INTERSECT doesn't check the LineString with the Point or Polygon, but the Bounding Box of the LineString, when a indicate a point OUTSIDE the Linestring BBox.
Intersects QUERY Where "rota" is the Linestring data:
SELECT Intersects(rota, createBuffer(GeomFromText('POINT(-19.7736 -43.7255)'),500))
FROM log_viagem WHERE rota IS NOT NULL;
How can I trust the MySQL Spatial now?
Or my concept about INTERSECTS is wrong?
SOLVED:
I didn't read the important note at 5.5 version of MySQL:
Note
Currently, MySQL does not implement these functions according to the specification. Those that are implemented return the same result as the corresponding MBR-based functions.
The Solution is taking with the server administrator to update to 5.6.1, there is an upgrade in the note
Note
MySQL originally implemented these functions such that they used
object bounding rectangles and returned the same result as the
corresponding MBR-based functions. As of MySQL 5.6.1, corresponding
versions are available that use precise object shapes. These versions
are named with an ST_ prefix. For example, Contains() uses object
bounding rectangles, whereas ST_Contains() uses object shapes.
As of MySQL 5.6.1, there are also ST_ aliases for existing spatial
functions that were already exact. For example, ST_IsEmpty() is an
alias for IsEmpty()