查询树中的父项

时间:2017-10-08 07:10:05

标签: android sqlite android-sqlite recursive-cte

我有数据库表任务如下。

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与各自的父任务相关。

e.g。任务名称' java' _id = 18,parentId = 15表示' java'是_id = 15的子任务,这是'语言'。

再次'语言' _id = 15,parentId = 6表示语言'是_id = 6的子任务,即编程'。

相同'编程'是软件开发的子任务'。

'软件开发'是null的子任务。

所以我需要一个查询,它输出如下所示输入_id = 18(即' java'),它是父项列表,父项任务的父项...子任务的顶部。

_id      name              parentId
4    Software Development   null
6    Programing             4
15   language               6
18   java                  15

目前,我可以在循环中使用4个查询来获取此输出。

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

在下一次迭代中,_id将是来自上述查询

输出的parentId的值

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

2 个答案:

答案 0 :(得分:1)

要在树中上升需要递归common table expression

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)之前不支持此功能。

答案 1 :(得分:0)

我也有这样的业务,我将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;
}