Android SQLite“order by”联合查询中的计算列

时间:2011-01-02 18:15:22

标签: sql android sqlite union calculated-columns

我一直在使用以下代码查询一个表:

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

上述代码一直令人满意。但是,我现在想将这个想法扩展到两个或更多表的UNION,并尝试了以下代码:

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:1st ORDER BY term与结果集中的任何列都不匹配”错误。

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

有人可以帮助我走上正轨吗?

3 个答案:

答案 0 :(得分:2)

一个完整的猜测(我不熟悉Android SQLLite,但是不熟悉其他数据库引擎):如果你将union的结果放入子查询中,然后从子查询中选择*并对这些结果进行排序,这是否有效?这样的事情(使用你的列/表/等),如果我在SQL Server中:

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

答案 1 :(得分: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 :(得分:0)

只是一些快速评论,

  1. 尝试使用SQL语句>
  2. ,而不是使用<Between
  3. 你应该花时间创建一个自定义的SQLite函数来返回半径内的项目,它会更好,并且更少搞乱查询。只需谷歌SQLite custom functions