I am using mySQL
and CodeIgniter
. I have some floating point numbers in my database such as
Take the first value from the following:
select * from table order by abs(value - $myvalue);
Assuming that you have a 10% tolerance (+/-) you could try something like:
select * from table
where value >= ($myvalue * .9) and value <= ($myvalue * 1.1)
order by abs(value - $myvalue) limit 1
Slightly updated stealing from others - this should return the nearest result in the assumed tolerance range. (Also, I just noticed the where was incorrect, apologies - now it should work).
Unfortunately, I think your database will probably do a full table scan for solutions that involve abs
, so they will be (very) slow once your table grows. A fast-running solution may be found in this earlier thread.
Get the largest value similar to $val:
SELECT * FROM tab WHERE val <= $val ORDER BY val DESC LIMIT 1
Get the smallest value similar to $val:
SELECT * FROM tab WHERE val >= $val ORDER BY val LIMIT 1
Get the closest value similar to $val in either direction:
SELECT * FROM tab ORDER BY abs(val - $val) LIMIT 1
(
select *
from table
where value >= $myvalue
order by value asc
limit 1
)
union
(
select *
from table
where value < $myvalue
order by value desc
limit 1
)
order by abs(value - $myvalue)
limit 1
This may look counter-intuitive but the speed will be greater than the other queries shown so far.
This is due to the fact that a greater than
and less than
query is quicker.
Then doing an ABS
on two values is nothing.
This will give you the quickest return in a single query I can think of.
Doing an ABS
on a whole table will be slow as it will scan the whole table.
In my case, I was using the browsers geolocations and trying to find a closest city/state based on the coordinates I had in a table.
table structure:
id zipcode city_state lat lon
1 12345 Example, GA 85.3 -83.2
Recommend testing this vigorously before using -- probably needs some tweaks, but I came up with this as a start
SELECT city_state,
zipcode,
( Abs( lat - -33.867886 )
+ Abs( lon - -63.987) ) AS distance
FROM zipcodes
ORDER BY distance
LIMIT 1;
For laravel users:
$city = Zipcodes::selectRaw
('city_state, zipcode, ( ABS( lat - ? ) + ABS( lon - ?) ) AS distance', [$lat, $lon])
->orderBy('distance')
->first();
echo $city->city_state
Hope this helps someone someday.