Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android sqlite sort on calculated column (co-ordinates distance)

I am using an SQLITE database to store latitudes and longitudes of locations.

I want to be able to sort the results by rough distance from the current location. I already have the current location of the device as a double (lat, lng), the lat and lng in the database are also doubles.

What I want is a query that will create a virtual column that I am able to sort the results by.

I currently use a function to show the distance for a selected record:

float pk = (float) (180/3.14159);
float a1 = (float) (db_lat / pk);
float a2 = (float) (db_lon / pk);
float b1 = (float) (current_lat / pk);
float b2 = (float) (current_lon / pk);
float t1 = FloatMath.cos(a1)*FloatMath.cos(a2)*FloatMath.cos(b1)*FloatMath.cos(b2);
float t2 = FloatMath.cos(a1)*FloatMath.sin(a2)*FloatMath.cos(b1)*FloatMath.sin(b2);
float t3 = FloatMath.sin(a1)*FloatMath.sin(b1);
double tt = Math.acos(t1 + t2 + t3);
double dist = (6366000*tt);

For example, a MySQL select could be (taken from: www.movable-type.co.uk):

Select Lat, Lon, acos(sin($lat)*sin(radians(Lat)) + cos($lat)*cos(radians(Lat))cos(radians(Lon)-$lon))$R As dist From MyTable ORDER BY dist DESC

Currently I select locations using the following:

public Cursor locationGetAllRows(long groupid) { try { return db.query(LOCATION_DATABASE_TABLE, new String[] { "_id", "lat","lon","groupid"}, "groupid="+groupid, null, null, null, null); } catch (SQLException e) { Log.e("Exception on query: ", e.toString()); return null; } }

OK so is it possible to use the SQLITE database in this way? If not the only option I can think of is to have an extra column, iterate through the rows running the above function on each row and filling out an extra column on the row, then sorting on that column?

like image 647
Scoobler Avatar asked Dec 29 '22 06:12

Scoobler


1 Answers

This won't completely help, but for situations like this, seriously consider using rawQuery() instead of query(), so you can pass in a full SQL statement vs. having to chop it into pieces.


Your bigger problem is that I don't see that SQLite has trigonometric functions.

You do not indicate how you are using the Cursor you are getting back from your query. For example, if you are putting the Cursor into some sort of CursorAdapter, you could:

  • convert the Cursor into an ArrayList<Position>, where Position is some Java class you define with your data
  • close the Cursor, to release the RAM it takes up
  • sort the ArrayList<Position> using Arrays.sort()
  • wrap the ArrayList<Position> in an ArrayAdapter<Position> and use that where you had been using your CursorAdapter
like image 114
CommonsWare Avatar answered Jan 12 '23 00:01

CommonsWare