【问题标题】:Android SQLite "order by" calculated column in union query联合查询中的Android SQLite“排序依据”计算列
【发布时间】:2011-01-04 17:58:36
【问题描述】:

我一直在用下面的代码查询一张表:

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 does not match any column in the result set”错误。

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

谁能帮我走上正确的道路,好吗?

【问题讨论】:

  • 是您要在 TableA 中排序的字段还是仅在 tableB 中排序的字段
  • TableA 和 TableB 都包含地理相关的数据项……每个表都有一个 Easting 和 Northing 字段(大致相当于经度和纬度)。排序顺序是距中心点的距离,因此通过从每行获取东距和北距,将计算字段应用于两个表中的每一行。
  • 嗯,这与您的问题无关。但是,最好使用 StringBuilder 而不是 string += string 操作。只是一个好的做法(如果您需要在应用中频繁执行这些操作,则会获得巨大的性能提升)
  • 感谢您的建议,Sarwar。

标签: sql android sqlite union calculated-columns


【解决方案1】:

一个完整的猜测(我不熟悉 Android SQLLite,但我不熟悉其他数据库引擎):如果您将联合的结果放入子查询中,然后从子查询中选择 * 并对这些结果进行排序,这可行吗?如果我在 SQL Server 中,这样的东西(与您的列/表/等):

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

【讨论】:

  • 感谢您的建议。谷歌搜索“Android sqlite subquery”会引发对名为 SQLiteQueryBuilder 的 Android 类的引用。我去看看。
  • 这是最好的解决方案,将您的两个查询合并为一个,然后应用 order by 它成功了!
【解决方案2】:

我想我的 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 毫秒内完成。

【讨论】:

    【解决方案3】:

    只是一些快速的cmets,

    1. 不要使用&gt;&lt;,尝试使用SQL语句Between
    2. 您应该花时间创建一个自定义 SQLite 函数来返回半径内的项目,这样会更好,并且减少查询混乱的变化。只需谷歌SQLite custom functions

    【讨论】:

    • 感谢这些建议。我忘记了“之间”。关于自定义函数,在这个线程中的讨论:stackoverflow.com/questions/2352320/… 表明在 Android 中使用自定义 sqlite 函数并不容易。
    猜你喜欢
    • 2013-09-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-09
    • 2019-03-12
    • 2023-01-09
    • 1970-01-01
    相关资源
    最近更新 更多