2011-04-16 128 views
3

如何對SELECT語句的記錄進行排序,以便它們代表有效的樹?MySQL SELECT Tree Parent IDs

我所有的嘗試都顯示嵌套在錯誤父節點下的子節點。什麼是最可靠的方法來實現這種排序?

數據

ID  Parent ID  Title 
-------------------------------------------- 
0  NULL   Root 
1  0    Node A 
2  0    Node B 
3  1    Sub-Node C 
4  1    Sub-Node D 
5  3    Sub-Node E 

輸出

ID  Parent ID  Title 
-------------------------------------------- 
0  NULL   Root 
1  0    Node A 
3  1    Sub-Node C 
5  3    Sub-Node E 
4  1    Sub-Node D 
2  0    Node B 

數據可視

Root 
    Node A 
     Sub-Node C 
      Sub-Node E 
     Sub-Node D 
    Node B 
+1

雖然下面提供的示例顯示了一些非常酷的查詢,但我不認爲它是提供可視化的數據層的工作。你可以使用PHP更簡單(並且更具視覺吸引力)。 – Blindy 2011-04-16 17:57:05

+0

@Bindin我同意你的意見。我希望能有一種性能高效的方式來通過簡單的查詢檢索結果,但它看起來並不像這樣很容易。想到的唯一解決方案是將PHP與一系列臨時數組進行排序。我只需要一個平面數組,但是需要爲相鄰數據進行排序。 – 2011-04-16 18:03:03

+0

看看這個答案爲相同的情況:http://stackoverflow.com/a/33699713/5559741 – wajeeh 2015-11-13 18:48:43

回答

5

按照@Bindy的建議,我已經用PHP實現了這種類型。以下是似乎相對容易解決這個問題的兩個功能。

protected function _sort_helper(&$input, &$output, $parent_id) { 
    foreach ($input as $key => $item) 
     if ($item->parent_id == $parent_id) { 
      $output[] = $item; 
      unset($input[$key]); 

      // Sort nested!! 
      $this->_sort_helper(&$input, &$output, $item->id); 
     } 
} 

protected function sort_items_into_tree($items) { 
    $tree = array(); 
    $this->_sort_helper(&$items, &$tree, null); 
    return $tree; 
} 

我很想聽聽是否有一個更簡單的方法,但這似乎工作。

+1

呼叫時傳遞參考已經在php5.4中刪除 – RouR 2013-08-14 04:38:38

+0

@RouR如果我記得這只是意味着你需要改變調用'_sort_helper'的方式。而是嘗試使用'$ this - > _ sort_helper($ input,$ output,$ item-> id);'和$ this - > _ sort_helper($ items,$ tree,null);'。讓我知道如果這有幫助,我會更新我的答案相應:) – 2013-08-14 13:11:34

12

您可以使用嵌套集合。看看這篇文章:

Managing Hierarchical Data in MySQL

作者描述了在SQL建築層次結構,完整的例子查詢了幾個不同的方法。這是關於這個主題的非常好的閱讀!

+0

優秀,正是我一直在尋找! – 2016-06-28 08:12:15

+1

我知道這是一個老問題,但僅供將來參考:嵌套集適用於大多數情況下正在讀取的樹結構,但很少更改(INSERT,UPDATE,DELETE),因爲在嵌套集中編寫選項的代價非常高昂: https://robsite.net/nested-sets-suck-on-how-not-to-map-trees-into-a-relational-database/ – Broco 2016-08-29 08:56:43

+0

謝謝,Broco!我同意這種解決方案。隨意張貼您自己的答案。這實質上是一個物化視圖! – 2016-08-29 12:25:03

0

我剛完成這個遞歸函數,並認爲這是一個關於該問題的優雅方式。以下是我做了一次基本的SELECT mysql查詢後所做的工作:

function orderChildren($data){ 
    $tree = array(); 
    foreach($data as $value){ 
     if($value['parent_id'] == null){ // Values without parents 
      $tree[$value['id']] = $this->goodParenting($value, $data); 
     } 
    } 
    return $tree; 
} 

private function goodParenting($parent, $childPool){ 
    foreach($childPool as $child){ 
     if($parent['id'] == $child['parent_id']){ 
      $parent['children'][$child['id']] = $this->goodParenting($child, $childPool); 
     } 
    } 
    return $parent; 
} 
0

這是另一種執行PHP函數的方法。

function buildTree() { 
    $data = array(); 
    $pointers = array(); 

    $sql = "SELECT ID,PARENT,TITLE FROM TREE ORDER BY TITLE ASC"; 
    $res = $this->db->query($sql); 

    while ($row = $res->fetch(PDO::FETCH_ASSOC)) { 
    if(!isset($pointers[$row['ID']])) { 
     $pointers[$row['ID']] = $row; 
    } 

    if(!empty($row['PARENT'])) { 
     if(!isset($pointers[$row['PARENT']])) { 
     $pointers[$row['PARENT']] = $row; 
     } 
     $pointers[$row['PARENT']][$row['ID']] = &$pointers[$row['ID']]; 
    } else { 
     $data[$row['ID']] = &$pointers[$row['ID']]; // This is our top level 
    } 
    } 

    unset($pointers); 
    return $data; 
}