Custom MySQL Order By depending on a PHP function value - php

I have a database like this
http://i.stack.imgur.com/MHEwr.jpg
I have a PHP function which will compute distance { get_distance ($person_location) } of that address from the user (web user).
I need to have a query which will use that function and return the data from the database order by distance from the user [Using { get_distance ($person_location) } function of PHP].
Can anyone help me please?

You can't sort your SQL results on the serverside by the result of a PHP function.*
There are two approaches to your general problem:
1. Move calculation to SQL
Your distance computation probably relies on geo-coordinates (latitude and longitude). Save this data for every address in the database and then do the distance computation in SQL as well.
Find more on how to do this in MySQL here: Fastest Way to Find Distance Between Two Lat/Long Points
Your todo list for this. Do the following things ONCE:
Get all your addresses from the DB
Calculate the geo coordinates for each address with your PHP API
Update your database and put those geo coordinates in extra columns
Do the following things from now on:
Every time you add a row to your table, calculate the geo coordinates beforehand with your API and add them as well
Every time you change an address in the database, calculate the new geo coordinates with your PHP API and update them as well
Every time you need to calculate the distance for the current user to all other addresses, do a SELECT query which computes the distance and does the sorting
2. Do everything in PHP
Query your database for all addresses, put them into a PHP array, compute the distance to the current user with your function and then sort your array.
I strongly suggest not to do that, however, and implement everything on the server-side (Approach 1).
* well in theory you could, by calulcating the distance for every address offline, updating a temporary table with the result, and then querying your table again using this temporary table to sort your results. However, this is even worse than doing everything in PHP, you shouldn't even consider this!

imho it is not possible to use PHP functions in your query, only thing like aggregate functions served by MySQL.
I guess you need to process through the data by PHP.

Related

Sort issue- Orderby non db column

I have a database with zipcodes, latitude and longitude. The other database I have has cars with zipcodes of their location. I have a function return the distance between the user location (pulled from ip address) and and the cars location (based on zipcode, latitude and longitude). I want to order the cars by the closest to the user. I am not sure the best method.
I would imagine a orderby(distance ASC), but distance isn't in the db and its obtained on a per user basis.
Language: PHP, MYSQL Framework: YII2
If this function is in MySQL (e.g. stored function) then you can order by this function fine using say, ORDER BY USER_DISTANCE(user, distance) or similar.
If the function is within PHP code (not-MySQL) then you would need to sort the results after you got the query back. PHP has various functions that would help you with this:
You likely want one of the user-defined sort functions found here:
http://php.net/manual/en/array.sorting.php

Include distance in search form

I would like to implement a search by distance on a website.
There must be a user in a living city can find all users living within 100 or 200 km for example.
I have a table in my database that stores all the cities and their coordinates.
I thought to create another table that would store the distance between all cities but my data base contains 36,000 cities and it may make a lot of records ...
How could I make this search more simply knowing that my project will be developed with Symfony and Doctrine?
Thank you beforehand
You can use the correct answer here to determine the distance between co-ordinates.
Measuring the distance between two coordinates in PHP
For performance reasons you need to use geospatial index to efficiently query such a database. For example MongoDB has a feature for this.
If performance is not an issue you can simply store locations in relational database table and calculate distances in SQL. See this question for some information about this solution: Geo-Search (Distance) in PHP/MySQL (Performance)

Sphinx Search Sorting/Ranking

I just recently discovered sphinx search which I want to use for my PHP application. I have a table of geolocations where every record stores a country code. For every user who uses the search function to look up geopositions, I know which country he is from.
How would I reweigh the results such that the matching results are ascending in distance to the country of the user? I already have calculated a distance matrix for each country to each other, which I can access via SQL. The country information in the geolocation database is stored as 2 letter ISO country code.
What is a good solution for this problem? I heard about UDFs, are they applicable for that problem? Is it possible to solve this problem more easily by reformatting my table?
Thank you very much.
The "easiest" way to solve this is to have coordinates for each country. You then store the coordinates for each record in the sphinx index, and when searching find the coordinates and us it in the search. This way sphinx caculates the distance dynamically.
Did you have coordinates likes this to create the matrix? But it also resupposes, you are just using a 'point' per country, if your matrix is more advanced, eg taking the closest point on the borders of each (to make disances between odd shaped countries better), then it wont work so well.
In theory you could perhaps do this with payloads, by using the country name as keywords, and the distance in a payload (arranged specially so that close disances have a high weight) but will probably be expensive to index, and might not work all that well in practice.

Levenshtein search

I work on a site which sells let's say stuff and offers a "vendors search". On this search you enter your city, or postal code, or region and a distance (in km or miles) then the site gives you a list of vendors.
To do that, I have a database with the vendors. In the form to save these vendors, you enter their full address and when you click on the save button, a request to google maps is made in order to get their latitude and longitude.
When someone does a search, I look on a table where I store all the search terms and their lat/lng.
This table looks like
+--------+-------+------+
| term | lat | lng |
+--------+-------+------+
So the first query is something very simple
select lat, lng from my_search_table where term = "the term"
If I find a result, I then search with a nice method for all the vendors in the range the visitor wants and print the result on a map.
If I don't find a result, I search with a levenshtein function because people writing bruxelle or bruxeles instead of bruxelles is something really common and I don't want to make a request to google maps all the time (I also have a "how many time searched" column in my table to get some stats)
So I request my_search_time with no where clause and loop through all results to get the smallest levensthein distance. If the smallest result is greater than 2, I request coordinates from google maps.
Here is my problem. For some countries (we have several sites all around the world), my_search_table has 15-20k+ entries... and php doesn't (really) like looping on such data (which I perfectly understand) and my request falls under the php timeout. I could increase this timeout but the problem will be the same in a few months.
So I tried a levensthein MySQL function (found on stackoverflow btw) but it's also very slow.
So my question is "is there any way to make this search fast even on very large datasets ?"
My suggestion is based on three things:
First, your data set is big. That means - it's: big enough to reject the idea of "select all" + "run levenshtein() in PHP application"
Second, you have control over your database. So you can adjust some architecture-related things
Finally, performance of SELECT queries is the most important thing, while performance for adding new data doesn't matter.
The thing is you can not perform fast levenshtein search because levenshtein itself is very slow. I mean, calculating levenshtein distance is a slow thing. Thus, you'll not be able to resolve the issue with only "smart search". You'll have to prepare some data.
Possible solution will be: create some group index and assign it during adding/updating data. That means - you'll store additional column which will store some hash (numeric, for example). When adding new data, you'll:
Perform search with levenshtein distance (for that you may either use your application or that function which you've (already mentioned) over all records in your table against inserted data
Set group index for new row to value of index which found rows in previous step have.
If nothing found, set some new group index value (it' the first row and there are no similar rows yet) - which will be different from any group index values that already present in table
To search desired rows, you'll need just select rows with same group index value. That means: your select queries will be very fast. But - yes, this will cause extremely huge overhead when adding/changing your data. Thus, it isn't applicable for case, when performance of updating/inserting matters.
You could try MySQL function SOUNDS LIKE
SELECT lat, lng FROM my_search_table WHERE term SOUNDS LIKE "the term"
You can use a kd-tree or a ternary tree to speed up the search. The idea is to use a binary search.

Storing multiple GPS coordinates in MySQL

I'm making an Android app that tracks a user and displays their location in real time. I have it working, but I'm having issues storing the coordinates in a database properly. Right now, the user's location will update every second, and it stores the location in a database and then the web app pulls the most recent from the database. I want to be able to store the list of locations in one row for a particular user. I read some about GeoSpatial information in MySQL, and I think that the linestring datatype would work, but I can't seem to find enough information about how to implement the query in PHP. Can someone provide an example of how to keep appending coordinates to the database in a linestring type using PHP? Or provide a suggestion of how to continually store coordinates using one row of a database.
Thanks
Simply store each point the user is located at into a table, along with an ID and timestamp. You can then assemble the points with a query.
Don't store an entire track in one row, or you won't be able to do much with the data later.
Edit: Here is what your table will look like:
gps_points
id (bigint)
user_id (int)
timestamp (timestamp or datetime, depending on your needs)
lat (double)
lon (double)
A GPS coordinate is a set of X,Y and Z float value, not a set of points to interpolate a curve (which essentially is what the linestring datatype is for). So I would store the points in 3 float columns with the additional information like a timestamp. If you need, you can extrapolate the linestring afterwards from the given data to show on a map.
Or you can just simply use Firebase for your database which is very flexible and you can easily work in firebase
My experience is that the UTM format is easier to store in a database since its orthogonal and has a really convenient syntax. And it is suitable for single line string too. You can find information and a handy class that easily converts between GPS and UTM here:
http://www.ibm.com/developerworks/java/library/j-coordconvert/index.html

Categories