2011-01-02 4 views
0

Я использую следующий код для запроса одну таблицу:Android SQLite «заказ на» вычисляемого столбца в запросе накидной

public Cursor fetchFilteredItemsNearSortedByDistance(String strTable, String[] strArrayFields, String strField, String strCriterion, double dblCentreEasting, double dblCentreNorthing, double dblRadius) { 

    String strSQL = "Easting > " + Double.toString(dblCentreEasting-dblRadius); 
    strSQL += " AND Easting < " + Double.toString(dblCentreEasting+dblRadius); 
    strSQL += " AND Northing > " + Double.toString(dblCentreNorthing-dblRadius); 
    strSQL += " AND Northing < " + Double.toString(dblCentreNorthing+dblRadius); 
    strSQL += " AND " + strField + " LIKE '%" + strCriterion + "%'"; 
    strSQL += " ORDER BY "; 
    strSQL += "((Easting - " + Double.toString(dblCentreEasting)+")"; 
    strSQL += " * (Easting - " + Double.toString(dblCentreEasting)+")"; 
    strSQL += " + (Northing - " + Double.toString(dblCentreNorthing)+")"; 
    strSQL += " * (Northing - " + Double.toString(dblCentreNorthing)+"))"; 
    strSQL += " COLLATE NOCASE"; 

    return myDbHelper.myDataBase.query(strTable, strExtendedArrayFields, strSQL, null, null, null, null);  
} 

Приведенный выше код работает удовлетворительно. Тем не менее, теперь я хочу, чтобы расширить идею объединения двух или более таблиц, и попытался следующий код:

public Cursor fetchFilteredPOIsNearSortedByDistance(String strTable, String[] strArrayFields, String strField, String strCriterion, double dblCentreEasting, double dblCentreNorthing, double dblRadius) { 

    String strSQL = "SELECT * FROM TableA "; 
    strSQL += "UNION SELECT * FROM TableB "; 
    strSQL += "WHERE (Easting > " + Double.toString(dblCentreEasting-dblRadius); 
    strSQL += " AND Easting < " + Double.toString(dblCentreEasting+dblRadius); 
    strSQL += " AND Northing > " + Double.toString(dblCentreNorthing-dblRadius); 
    strSQL += " AND Northing < " + Double.toString(dblCentreNorthing+dblRadius); 
    strSQL += " AND " + strField + " LIKE '%" + strCriterion + "%') "; 
    strSQL += " ORDER BY "; 
    strSQL += "((Easting - " + Double.toString(dblCentreEasting)+")"; 
    strSQL += " * (Easting - " + Double.toString(dblCentreEasting)+")"; 
    strSQL += " + (Northing - " + Double.toString(dblCentreNorthing)+")"; 
    strSQL += " * (Northing - " + Double.toString(dblCentreNorthing)+"))"; 
    strSQL += " COLLATE NOCASE"; 

    return myDbHelper.myDataBase.rawQuery(strSQL, null); 
} 

Однако, это производит «SQLiteException: первый ORDER BY срок не соответствует ни один столбец ошибка результата ".

Полная ошибка в LogCat является:

ERROR/AndroidRuntime(11444): Caused by: android.database.sqlite.SQLiteException: 1st ORDER BY term does not match any column in the result set: , while compiling: SELECT * FROM TableA UNION SELECT * FROM TableB WHERE (Easting > 594378.8427734375 AND Easting < 663822.8427734375 AND Northing > 127586.046875 AND Northing < 197030.046875 AND Name LIKE '%%') ORDER BY ((Easting - 629100.8427734375) * (Easting - 629100.8427734375) + (Northing - 162308.046875) * (Northing - 162308.046875)) COLLATE NOCASE 

Может кто-нибудь помочь мне на правильном пути, пожалуйста?

+0

Простые поля, которые вы хотите заказать в TableA или только в таблицеB –

+0

В таблице A и TableB содержатся географически связанные элементы данных ... каждая таблица имеет поле Easting и Northing (в широком смысле эквивалентное долготе и широте). Порядок сортировки - это расстояние от центральной точки, так что вычисленное поле применяется к каждой строке в обеих таблицах, принимая восток и север от каждой строки. – prepbgg

+0

Ну, это не связано с вашим вопросом. Но лучше вы StringBuilder вместо строки + = операции с строкой. Просто хорошая практика (и огромный прирост производительности, если вы часто требуете этих действий в своем приложении). –

ответ

1

Я думаю, что я, должно быть, допустил некоторые ошибки в синтаксисе моего SQL.

В упрощенном виде, код, который не сделал работа:

SELECT * FROM TableA UNION SELECT * FROM TableB 
WHERE (FieldA > X1 AND FieldA < X2 AND FieldB > Y1 AND FieldB < Y2 
AND FieldC LIKE '%Criterion%') 
ORDER BY [Function of FieldA and FieldB] COLLATE NOCASE 

Я теперь заменили это с:

SELECT FieldA, FieldB, FieldC, .... , 
[Function of FieldA and FieldB] AS CalculatedField 
FROM TableA 
WHERE FieldA BETWEEN X1 AND X2 
AND FieldB BETWEEN Y1 AND Y2 
AND FieldC LIKE '%Criterion%' 
UNION 
SELECT FieldA, FieldB, FieldC, .... , 
[Function of FieldA and FieldB] AS CalculatedField 
FROM TableB 
WHERE FieldA BETWEEN X1 AND X2 
AND FieldB BETWEEN Y1 AND Y2 
AND FieldC LIKE '%Criterion%' 
ORDER BY CalculatedField COLLATE NOCASE 

Хотя SQL заявление гораздо больше, кажется, работает, и что более удивительно быстро ... фильтрация примерно на 10 000 строк данных и сортировка всего происходит менее чем за 50 миллисекунд.

2

Полная догадка (я не знаком с Android SQLLite, но есть другие механизмы БД): Если вы поместите результат своего объединения в подзапрос, а затем выберите * из подзапроса и закажите эти результаты, это работает? Что-то вроде этого (с вашей колонки/таблицы/и т.д.), Если бы я был в SQL Server:

SELECT tblResults.* FROM 
    (SELECT X FROM tblA 
    UNION 
    SELECT X FROM tblB) AS tblResults 
ORDER BY tblResults.X 
+0

Спасибо за это предложение. Googling для «подзапроса sqlite для Android» выдает ссылку на класс Android, называемый SQLiteQueryBuilder. Я посмотрю на это. – prepbgg

+0

Это лучшее решение, объедините ваши два запроса как одно, а затем примените 'order by', он сработал! –

0

только некоторые быстрые комментарии,

  1. Вместо использования > и <, попробуйте использовать SQL оператор Between
  2. Вам нужно потратить время на создание пользовательской функции SQLite для возврата элементов внутри радиуса, это будет лучше и с меньшим изменением беспорядка запроса. Просто google SQLite custom functions
+0

Спасибо за эти предложения. Я забыл о «Между». Переменные пользовательские функции, обсуждение в этом потоке: http: // stackoverflow.com/questions/2352320/sqlite-on-android-how-to-create-a-sqlite-dist-db-function-to-be-used-in-the-ap предполагает, что совсем не легко использовать пользовательские sqlite в Android. – prepbgg

Смежные вопросы