2011-01-02 10 views
0

Ich habe den folgenden Code wurde unter Verwendung einer Tabelle abzufragen:Android SQLite "order by" berechnete Spalte in Union-Abfrage

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);  
} 

Der obige Code hat zufriedenstellend gearbeitet. Allerdings möchte ich jetzt die Idee, eine Vereinigung von zwei oder mehr Tabellen zu erweitern, und haben den folgenden Code versucht:

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); 
} 

Doch dies erzeugt ein „SQLiteException: 1. ORDER BY Begriff keine Spalte passen in das Ergebnis setzt "Fehler.

Der vollständige Fehler in LogCat ist:

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 

jemand mich auf dem richtigen Weg helfen kann, bitte?

+0

Sind drei Felder, die Sie in TabelleA oder nur in TabelleB bestellen möchten –

+0

Tabelle A und TabelleB enthalten beide geographisch verwandte Datenelemente ... jede Tabelle hat ein Rechtswert- und ein Neigungsfeld (entspricht weitgehend Längen- und Breitengrad). Die Sortierreihenfolge ist die Entfernung von einem zentralen Punkt, also wird ein berechnetes Feld auf jede Zeile in beiden Tabellen angewendet, indem von jeder Zeile die Ost- und Nordrichtung genommen wird. – prepbgg

+0

Nun, das hängt nicht mit Ihrer Frage zusammen. Aber besser Sie StringBuilder anstelle der String + = String-Operationen. Nur eine gute Praxis (und eine enorme Leistungssteigerung, wenn Sie häufig zu diesen Aktionen in Ihrer App aufgefordert werden) –

Antwort

1

Ich denke, ich muss einige Fehler in der Syntax meines SQL gemacht haben.

Vereinfacht ausgedrückt, wird der Code, der nicht funktioniert hat war:

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 

ich jetzt diese mit ersetzt:

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 

Obwohl diese SQL-Anweisung viel länger ist, es scheint zu funktionieren, und was mehr ist, ist erstaunlich schnell ... die Filterung von etwa 10.000 Zeilen von Daten und Sortierung geschieht in weniger als 50 Millisekunden.

2

Eine komplette Schätzung (ich bin nicht vertraut mit Android SQLLite, aber bin andere DB-Engines): Wenn Sie das Ergebnis Ihrer Union in eine Unterabfrage und wählen Sie dann * aus der Unterabfrage und bestellen diese Ergebnisse, funktioniert das? So etwas wie diese (mit Spalten/Tabellen/etc.), Wenn ich in SQL Server waren:

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

Danke für diesen Vorschlag. Googling für "Android sqlite Unterabfrage" wirft einen Verweis auf eine Android-Klasse namens SQLiteQueryBuilder. Ich werde es mir ansehen. – prepbgg

+0

Dies ist die beste Lösung, verschmelzen Sie Ihre beiden Abfragen als eine und wenden Sie dann 'order by' an, es hat funktioniert! –

0

nur ein paar schnelle Kommentare,

  1. Statt mit > und <, versuchen, die SQL verwenden Anweisung Between
  2. Sie sollten Zeit in das Erstellen einer benutzerdefinierten SQLite-Funktion investieren, um die Elemente innerhalb des Radius zurückzugeben, es wird besser und mit weniger Änderung der Abfrage verwirrend sein. Einfach googeln SQLite custom functions
+0

Danke für diese Vorschläge. Ich hatte "Zwischen" vergessen. Re benutzerdefinierte Funktionen, die Diskussion in diesem Thread: http: // stackoverflow.com/questions/2352320/sqlite-on-android-how-to-create-a-sqlite-dist-db-funktion-zu-verwendet-in-the-ap schlägt vor, dass es überhaupt nicht einfach ist, benutzerdefiniert zu verwenden SQLite-Funktionen in Android. – prepbgg