我的SQLite
数据库表中存储了一些位置坐标。我想从使用当前位置检索1公里范围内的位置。现在我从数据库中获取所有值,并编写了一个方法来检索我的范围内的值。这使我的开销很大,因为我的表可能包含超过1000个坐标。
所以我正在寻找一种更好的方法来做到这一点。是否可以直接使用SELECT查询直接检索我的范围内的位置? 我找到了question 1和question 2,但无法找到可能的解决方法。非常感谢任何帮助。
这是我的SELECT查询:
String selectQuery = "SELECT "+COLUMN_OBJECTID+","+COLUMN_OBJECTNAME_ENGLISH+","
+COLUMN_OBJECTNAME_ARABIC+","+COLUMN_OBJECTLATITUDE+","+COLUMN_OBJECTLONGITUDE+","
+COLUMN_OBJECTCATEGORYID+","+COLUMN_OBJECTADDRESS_ENGLISH+","+COLUMN_OBJECTADDRESS_ARABIC
+" FROM " + TABLE_OBJECTLIST+" WHERE "+COLUMN_OBJECTCATEGORYID+"='"+categoryId+"' AND "+
((userLat-Double.parseDouble(COLUMN_OBJECTLATITUDE))*(userLat-Double.parseDouble(COLUMN_OBJECTLATITUDE))
+(userLong-Double.parseDouble(COLUMN_OBJECTLONGITUDE))*(userLong-Double.parseDouble(COLUMN_OBJECTLONGITUDE))<=range);
答案 0 :(得分:1)
您可以使用以下where条件编写SQL查询:
where ( (my_lat - LAT)*(my_lat - LAT) + (my_lon - LON)*(my_lon - LON) ) <= 1KM
这个想法是使用毕达哥拉斯方法来计算近似位置和基于此的过滤器。 这里我没有采用平方根,因为我猜SQLite中的SQL函数没有sqrt。
这适用于近似计算...
我使用了以下SQL并且它有效...
// Table with columns as String and Float
CREATE TABLE "locations" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL , "lat_string" VARCHAR, "long_string" VARCHAR, "lat_val" FLOAT, "long_val" FLOAT)
// Insert example data
INSERT INTO "locations" VALUES(1,'12.9587926','77.7477416',12.9587926,77.7477416);
INSERT INTO "locations" VALUES(2,'12.9973486','77.6967362',12.9973486,77.69673619999999);
INSERT INTO "locations" VALUES(3,'12.9715987','77.5945627',12.9715987,77.5945627);
INSERT INTO "locations" VALUES(4,'12.9629354','77.7122996',12.9629354,77.7122996);
// Select when column format is string. This works in SQLIte
SELECT id, ( (77.7580827 - long_string)*(77.7580827 - long_string) + (12.9905542 - lat_string)*(12.9905542 - lat_string) ) as dist FROM locations
// Select when column format is float. This works in SQLIte
SELECT id, ( (77.7580827 - long_val)*(77.7580827 - long_val) + (12.9905542 - lat_val)*(12.9905542 - lat_val) ) as dist FROM locations
答案 1 :(得分:1)
以下是一些代码,可以让您了解如何使其正常工作:
public static double[] getNeighbourhoodArea(
final double lat, final double lng, final int distInMtrs) {
double[] area = new double[4];
final double latRadian = Math.toRadians(lat);
final double degLatKm = 110.574235;
final double degLngKm = 110.572833 * Math.cos(latRadian);
final double deltaLat = distInMtrs / 1000.0 / degLatKm;
final double deltaLong = distInMtrs / 1000.0 / degLngKm;
final double minLat = lat - deltaLat;
final double minLng = lng - deltaLong;
final double maxLat = lat + deltaLat;
final double maxLng = lng + deltaLong;
area[0] = minLat;
area[1] = minLng;
area[2] = maxLat;
area[3] = maxLng;
return area;
}
/**
* search POIs in the neighbourhood
*/
private PntInrtst collectPOIs(double lat, double lng) {
if (mDb == null) return Const.NULL_POI;
Cursor cursorStat = mDb.getPoisInArea(lat, lng, Const.SIDE_LENGTH_GEO_OFFSET);
double area[] = Logic.getProtectionArea(lat, lng, Const.SIDE_LENGTH_GEO_OFFSET);
ArrayList<PntInrtst> poiArray = new ArrayList<PntInrtst>();
PntInrtst poi = Const.NULL_POI;
if (cursorStat.moveToFirst()) {
for (int i = 0; i < cursorStat.getCount(); i++) {
double potLat = cursorStat.getFloat(Const.COL_LA);
double potLng = cursorStat.getFloat(Const.COL_LO);
if ((potLat < area[Const.MAX_LAT] && potLat > area[Const.MIN_LAT])
&& (potLng < area[Const.MAX_LNG] && potLng > area[Const.MIN_LNG])) {
poi = Logic.getPoiByCursor(getApplicationContext(), cursorStat);
poiArray.add(poi);
}
cursorStat.moveToNext();
} // End "Cursor"
}
cursorStat.close();
// more than once, fire the nearest
if (poiArray.size() > 1) return closest(poiArray, lat, lng);
else return poi; // one or null
}
/**
* filter POIs which won't be useful (avoids flooding the cache)
*/
public Cursor getPoisInArea(double latitude, double longitude, int range) {
double area[] = getNeighbourhoodArea(latitude, longitude, range);
String where = "la" + "<" + area[MAX_LAT] +
" AND " + "la" + ">" + area[MIN_LAT] +
" AND " + "lo" + "<" + area[MAX_LNG] +
" AND " + "lo" + ">" + area[MIN_LNG];
SQLiteDatabase db = mDbHelper.getReadableDatabase();
return db.query(Const.POI_DB_TABLE, null, where, null, null, null, null);
}