2017-10-08 117 views
1

我有數據庫表任務如下。查詢樹中的父母

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意味着'language'是_id = 6的子任務,它是'編程'。

同樣的'程序'是'軟件開發'的子任務。

而'軟件開發'是空的子任務。

所以我需要一個查詢,其輸出如下輸出_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

答案是CTE(公用表表達式)。查看WITH語句。 https://sqlite.org/lang_with.html這是查詢SQL中樹結構的常用方法(基本上就是你所擁有的) –

+0

https://en.wikipedia.org/wiki/Hierarchical_and_recursive_queries_in_SQL –

回答

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)之前不被支持。

+0

謝謝你的回答!我得到的輸出與上面的查詢是 18 | java | 15而不是所需的輸出。你的方法似乎寫,但仍然缺少一些東西! – Kevan

+0

糟糕,連接條件錯誤... –

+0

'WITH'支持來自sqlite 3.8.3或更高版本 –

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; 
} 
+0

而且從sqlite版本3.8.3支持WITH子句。也許你可以使用'WITH子句' –