Number of digits from floating point values in a mysql query? - mysql

select name, lat, lng from locations limit 10
What if I want a specific number of digits after the decimal place for lat & lng which happen to be floating point values?

If X is the number of digits you want:
select name, round(lat, X, 1), round(lng, X, 1)
from locations limit 10
If you want it to round as well as truncate, take out the 1 parameter of the round function.

Let suppose you want to get .3
select name , lat , lng from locations
where lat like '%.3' and lng like '%.3'
limit 10

Related

How to get more precision for a computed distance in MySQL, without using geometric types?

I must compute the distance between an object (a city) and each of the several entries from a MySQL table I have (some restaurants). This city and the restaurants are located in a same country.
The computed distance is used in order to show all the restaurants which are close to this city ; the threshold distance is arbitrary. Moreover, this is a ranked list: the closest restaurants are shown first, and the farest are shown at end-of-list. My problem is about this ranking.
What I've done for now
So I made some researches and I succeeded in computing this distance.
$special_select_distance = "DEGREES(ACOS(COS(RADIANS(" . $oneVilles->__get('latitude')[app::getLang()] . ")) * COS(RADIANS(lat)) * COS(RADIANS(lon) - RADIANS(" . $oneVilles->__get('longitude')[app::getLang()] . ")) + SIN(RADIANS(" . $oneVilles->__get('latitude')[app::getLang()] . ")) * SIN(RADIANS(lat))))";
$restaurants = $restaurantsDAO->getAll(null, ['distance DESC'] , null, 'HAVING distance < 1.9' , null , '*, ' . $special_select_distance . " AS distance");
... where:
['distance DESC'] stands for the ranking by distance
'HAVING distance < 1.9' stands for the arbitrary threshold
'*, ' . $special_select_distance . " AS distance" is the selector
$oneVilles->__get('latitude')[app::getLang()] and $oneVilles->__get('longitude')[app::getLang()] are the city's coordinates lat and lon
lat and lon are the restaurant's coordinates (automatically taken into the table we are iterating on, i.e.: restaurants table, since we use the restaurants DAO)
Question
Actual and unexpected result
For each of the restaurants that are quite close between themselves, the computed distance with the city remains the same.
Example: assume that restaurants A and B are quite close. Then, the distance between A and the city is the same than B and the city, it's my actual and unexpected result.
This is not what I want. Indeed, in reality one of these restaurants is closest to the city than the other. I think there isn't enough precision in MySQL.
Expected result
Expected result: to make the restaurants ranking according to the distance to the city working. In other words, to get a more precise computed distance.
Example: assume that restaurants A and B are quite close. Then, the distance between A and the city is shorter than B and the city, it's my expected result.
Examples of computed distances
Between a restaurant and the city (the restaurant being far from the city): 1.933156948976873
Between a restaurant A and the city (A being close to the city): 1.6054631070094885
Between a restaurant B and the city (B being close to A): 1.6054631070094885
Distances in points 2. and 3. are the same and it's not normal. I would want to have more digits, in order to be able to rank my restaurants more efficiently.
Constraints
I wouldn't want to change the configuration of the MySQL Server.
In particular: I absolutely can't use MySQL geometric types (it's a firm's constraint)
The expected solution should simply change the SQL query I wrote and provided to you, in order to be more precise, if it's possible.
Other methods of calculating the distance are allowed, if necessary.
For long distances, use the Haversine formula for accuracy. For short distances, Pythagoras is twice as fast.
16 significant digits (data type DOUBLE) is ludicrous. You don't need to distinguish two different fleas on your dog.
With Pythagoras, be sure to divide the longitude by the cosine of the latitude -- One degree of longitude near Helsinki is half as far as one degree at the equator.
Some more details here: http://mysql.rjweb.org/doc.php/latlng
If 1.6054631070094885 is a latitude diff, then think about it this way: If you and I are at the same longitude, but our latitudes are 1.605463 and 1.605464, then, well, I don't know you well enough to be that close.
It is not practical to compare two floating point values without having a fudge factor:
If abs(a-b) < 0.00001, then treat them as equal.
More
I recommend FLOAT for lat, lng, and distance since you are talking about restaurants. If you are not talking about more than, say, 100 miles or km, then this expression is sufficiently precise:
SQRT( ($lat - lat) *
($lat - lat) +
(($lng - lng) * COS(RADIANS(lat))) *
(($lng - lng) * COS(RADIANS(lat))) ) * $factor
Where...
lat and lng are names of FLOAT columns in the table, in units of degrees.
$lat and $lng are values of the location you are starting from, also in degrees. (PHP uses $; other languages use other conventions.)
$factor is 69.172 for miles or 111.325 for kilometers.
I would not display the result with more than perhaps 1 decimal place. (Don't display "12.345678 miles"; "12.3 miles" is good enough.)
A comparison of Pythagoras and GCD:
Pyt GCD
To Rennes: 93.9407 93.6542
To Vannes: 95.6244 95.6241

SQL - Agg Func Manhattan Distance

SO Link doesn't answer the question. I can't figure out how to solve this query on Hackerspace. None of the solutions online seem to be working. Is this a bug or am I doing something wrong?
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 minimum value in Western Longitude (LONG_W in STATION).
c happens to equal the maximum value in Northern Latitude (LAT_N in STATION).
d happens to equal the maximum value in Western Longitude (LONG_W in STATION).
Query the Manhattan Distance between points and and round it to a scale of decimal places.
Input Format
The STATION table is described as follows:
STATION Table
ID | Number
City | VarChar2(21)
State | VarChar2(2)
LAT_N | Number
LONG_W | Number
Database: MySQL
Source: https://www.hackerrank.com/challenges/weather-observation-station-18/problem
Link: distance between two longitude and latitude (Tried, but none of the answers provided work.)
SELECT ROUND(ABS(MIN(Station.LAT_N) - MIN(Station.LONG_W)) + ABS(MAX(Station.LAT_N) - MAX(Station.Long_W)), 4)
FROM Station;
The formula for manhattan distance is | a - c| + | b - d| where a and b are min lat and long and c and d are max lat and long respectively.
select
round(
abs(
min(lat_n)- max(lat_n)
) + abs(
min(long_w)- max(long_w)
), 4
)
from
station;
I got 25 hakker points! so can I get 25 points from you?
Without just writing the answer: you need to calculate the horizontal difference between the min and max longitude, and add the vertical difference between the min and max latitude.
Your code does something a bit different. If you update your code accordingly, then the rest is OK and will be marked as correct by hackerrank.
You are comparing latitude and longitude when instead you need to compare latitude with latitude and longitude with longitude. The Manhattan distance between (1,3) and (2,4) is |1-2|+|3-4|, not |1-4|+|2-3|.
It should also be pointed out that since you're taking the min and max of the same range, you don't actually need the absolute value function. round(max(x)-min(x)+max(y)-min(y), 4) works perfectly well - and is slightly faster.
My answer for MS SQL
SELECT CAST(
ABS(MAX(LAT_N) - MIN(LAT_N)) + ABS(MAX(LONG_W) - MIN(LONG_W))
AS DECIMAL(20, 4))
FROM STATION
select round((max(lat_n)-min(lat_n)),4)+round((max(long_w)-min(long_w)),4)
from station;
As we will get result from diff of max and min we don't need abs.
The above code works for Sql Problem
SELECT ROUND(ABS(MAX(Station.LAT_N) - MIN(Station.LONG_W)) + ABS(MIN(Station.LAT_N) - MAX(Station.Long_W)), 4)
FROM Station;enter image description here

Select records based zipcode, it's radius, lat and lon in MySQL

Below is my company table with it's postalcode, lat, lon and the radius in kilometers where each company is able to provide his services.
id company_name city postalcode radiu latitude longitude
1 A Drogteropslagen 7705 PA 10 52.61666700 6.50000000
2 B Coevorden 7740 AA 15 52.66666700 6.75000000
3 C Emmen 7812 TN 5 52.78333300 6.9000000
4 D Emmer-Compascuum 7881 PZ 25 52.81666700 7.05000000
5 E Nieuw-Dordrecht 7885 AA 60 52.75000000 6.96666700
I would like to select the companies which a particular postalcode e.g. 7813 AB lives within their postalcode + the radius, even this postalcode 7813 AB is not exact the same as that of a company. how to write a sql query to select those companies?
SELECT t1.company_name, t2.company_name,
(6371 * acos(cos(radians(t1.lat1)) * cos(radians(t2.lat2))
* cos(radians(t2.lng2) - radians(t1.lng1)) + sin(radians(t1.lat1)) * sin(radians(t2.lat2)))) AS distance,
t1.radius
FROM
(
SELECT company_name, latitude AS lat1, longitude AS lng1,
radius
FROM company
WHERE postalcode = '7813 AB'
) t1
CROSS JOIN
(
SELECT company_name, latitude AS lat2, longitude AS lng2
FROM company
) t2
HAVING distance < t1.radius AND t1.company_name != t2.company_name
You will need to convert the input post code to long/lat coordinates.
There are two ways to do this; the most performant way is to import a table with post code and long/lat coordinates. You can find a dataset here for the Netherlands.
The alternative is to use a geocoding API; there are several available; Google is your friend. This can be a performance problem (if you have thousands of customers all submitting post codes at the same time), and may require licensing from the API provider.
Once you have the long/lat for your input post code, you can use geo-spatial logic in MySQL to calculate what's in the radius.
You can use spatial datatypes for longitude and latitude (or convert them) and then calculate the difference with st_difference, see https://dev.mysql.com/doc/refman/5.7/en/spatial-operator-functions.html#function_st-difference
Example:
SELECT st_distance(POINT(50.0, 8.0), POINT(latitude, longitude)) FROM company;
The distance is, however, a approximation and works best for small distances. With longer distances the calculation error increases due to the fact, that MySQL only calculates planar coordinates (Euclidean geometry).

T-SQL: Finding the closest location of an object on a map grid

I have grid showing on a map. I know your location and the location of 2 objects on the map. Objects appear where grid lines cross. Consider the world flat and not round since the area on the map is only a short distance. I want to determine which object is closest to you without using trigonometry and multiplication for performance reasons. I'm not looking for accuracy as much as just getting a ballpark indication. I should be able to determine the shortest distance between the difference in latitude and longitude from my current location. My table, Locations, looks like this:
ID Latitude Longitude
1 50 70
2 30 40
If my location is Latitude = 40 and Longitude = 60, then the location with ID = 1 would be closer to me.
If my location is Latitude = 30 and Longitude = 60, probably both locations are about the same distance, so just pick one.
If my location is latitude = 30 and Longitude = 50, then the location with ID = 2 would be closer.
You really need to use some trigonometry to get any kind of accuracy:
DECLARE #LocationTable TABLE(ID int, Latitude int, Longitude int)
INSERT INTO #LocationTable(ID, Latitude, Longitude)
VALUES
(1,50,70),
(2,30,40)
DECLARE
#MyLatitude int = 90,
#MyLongitude int = 40
WITH DistanceTable AS
(
SELECT ID, Latitude, Longitude,
SQRT(POWER(Latitude - #MyLatitude,2) + POWER(Longitude - #MyLongitude, 2)) AS Distance
FROM #LocationTable
)
SELECT ODT.ID, ODT.Latitude, ODT.Longitude, ODT.Distance
FROM (SELECT ID, Latitude, Longitude, Distance, ROW_NUMBER() OVER(ORDER BY Distance) AS Position
FROM DistanceTable) AS ODT
WHERE ODT.Position = 1;
I would just do a min of the sum of the differences. I tried it out,and it works pretty well.
SELECT MIN(ABS(s.Latitude - 47) + ABS(s.Longitude - -122)), s.ID FROM Sites as s Group By ID;
SELECT MIN(((s.Latitude - #lat)(s.Latitude - #lat)) + ((s.Longitude - #lon)(s.Longitude - #lon))), s.ID FROM Sites as s Group By ID;

Retrieve coordinates from MySQL Geometry column

I just started using the MySQL Geospatial extension in hope of speeding up lat/lng range searches in my database of 500K points. A new GEOMETRY column p is created.
Problem:p & AsText(p) values returned are simply (BLOB), not in decimal degrees. No values are returned by GeomFromText(p). Because I had the redundant lat and lng columns, I still manage to get the lat lng values that I need. But I'm thinking of removing the lat and lng cols and just rely on p.
Converted existing Lat/Lng values to Points
UPDATE listings SET p = GeomFromText('POINT(39.948177 -75.174324)') WHERE listing_id = '585221';
Attempt to Retrieve Lat Lng from GEOMTRY col p
SELECT listing_id, lat, lng, GeomFromText(p), AsText(p), p from listings WHERE MBRContains( GeomFromText('Polygon((39 -76, 40 -76, 40 -74, 39 -74, 39 -76))'), p)
If you use AsText you will get your object in WKT format. To extract point coordinates use:
SELECT listing_id X(p), Y(p)
FROM listings
WHERE MBRContains( GeomFromText('Polygon((39 -76, 40 -76, 40 -74, 39 -74, 39 -76))'), p)
MySQL probably returns result of AsText as BLOB because it can get really long for complex objects. It's just that whatever you are using to display results can't cope with that, but the text is there.