查询树中的父母

我有数据库表任务如下。

SELECT _id,name,parentId FROM Task; _id name parentId ---------- -------------------- ---------- 4 Software Development 5 Machine Learning 6 Programing 4 7 Build System 4 8 version control 4 9 Android App Developm 4 10 Udacity Cource 5 11 Mathematics 5 12 skLearn docs 5 13 problem solving 6 14 breakdown 13 15 language 6 16 c 15 17 c++ 15 18 java 15 19 kotlin 15 20 gradle 7 21 bazel 7 22 git 8 23 svn 8 

在一个表中,所有的任务及其子任务使用_id(主键)和parentId与各自的父任务相关。

例如,任务名称“java”具有_id = 18,parentId = 15意味着“java”是_id = 15的子任务,即“语言”。

“语言”再次具有_id = 15和parentId = 6意味着“语言”是_id = 6的子任务,即“编程”。

同样的“编程”是“软件开发”的子任务。

而“软件开发”是null的子任务。

所以我需要一个查询给输出如下输出_id = 18(即'java'),是父任务的父母,父任务的父母…的子任务的顶部。

 _id名称parentId
 4软件开发null
 6编程4
 15语言6
 18 java 15

目前我能够在一个循环中使用4个查询来获取这个输出。

 SELECT _id,name,parentId FROM task WHERE _id = 18 

在下一次迭代中,_id将是上述查询的输出中parentId的值

这很耗时,所以我们可以有更好的解决方案。

在树中上去需要一个递归的公用表表达式 :

 WITH RECURSIVE parents(id, name, parentid, level) AS ( SELECT _id, name, parentid, 1 FROM Task WHERE _id = 18 UNION ALL SELECT Task._id, Task.name, Task.parentid, level + 1 FROM Task JOIN parents ON Task._id = parents.parentid ) SELECT id, name, parentid FROM parents ORDER BY level DESC; 

Android Lollipop(API级别21)之前不支持此功能。

我也有这样的业务,我结合SQL与Java代码来解决这个问题。 就像这样:

  public ArrayList<String> getRecursiveReverse(String parentId) throws Exception { StringBuffer sqlObject = new StringBuffer(); sqlObject.append("SELECT T.TABLE_ID "); sqlObject.append("FROM TABLE_NAME T "); sqlObject.append("WHERE 1 = 1 "); sqlObject.append(" AND T.STATUS = 1 "); sqlObject.append(" AND T.PARENT_ID = ? "); Cursor c = null; String[] params = { parentId }; ArrayList<String> listIdArray = new ArrayList<String>(); if (!StringUtil.isNullOrEmpty(parentId)) { listIdArray.add(parentId); } try { c = rawQuery(sqlObject.toString(), params); if (c != null) { if (c.moveToFirst()) { do { String tableId = CursorUtil.getString(c, "TABLE_ID"); ArrayList<String> tempArray = getShopRecursiveReverse(tableId); listIdArray.addAll(tempArray); } while (c.moveToNext()); } } } finally { try { if (c != null) { c.close(); } } catch (Exception e) { MyLog.w(getTAG(), GlobalUtil.getCurrentMethodName(), e); } } return listIdArray; } 
Interesting Posts