2012-05-15 34 views
5

我有鄰接表模式結構這樣的,我想指望根據父級別的所有冠軍一樣Food = (2,4,3), Fruit = (3,3)計數結果根據級別

樹TABEL結構

enter image description here

後,使樹一樣,

enter image description here

這段代碼即時得到正確的TOT人喜歡的食物= 9,水果= 6

function display_children($parent, $level) 
{ 

$result = mysql_query('SELECT title FROM tree '.'WHERE parent="'.$parent.'"'); 
$count = 0; 
    while ($row = mysql_fetch_array($result)) 
    { 
    $data= str_repeat(' ',$level).$row['title']."\n"; 
    echo $data; 
    $count += 1 + $this->display_children($row['title'], $level+1); 
    } 
    return $count; 
} 

通話功能

display_children(Food, 0) 

結果:9 //但我想導致像2,4,3

但我想獲得數一樣,對食品2,4,3以及根據水果3,3級總成績

所以PLZ指南如何根據總水平

+0

爲什麼只有'(2,4,3)' ?爲什麼'(9,11)'被擱置在一邊?你只需要最左邊的分支? – vyegorov

+0

bcoz我想顯示按照級別計數 –

+0

你是指'按照計數水平'?請解釋'(2,4, 3)'不同於'(9,11)'?你需要根部最深的分支嗎? – vyegorov

回答

2

如果你想獲得的級別數量,然後進行功能逐級返回它們。

function display_children($parent, $level) 
{ 

$result = mysql_query('SELECT title FROM tree WHERE parent="'.$parent.'"'); 
$count = array(0=>0); 
    while ($row = mysql_fetch_array($result)) 
    { 
    $data= str_repeat(' ',$level).$row['title']."\n"; 
    echo $data; 
    $count[0]++; 
    $children= $this->display_children($row['title'], $level+1); 
    $index=1; 
    foreach ($children as $child) 
    { 
    if ($child==0) 
     continue; 
    if (isset($count[$index])) 
     $count[$index] += $child; 
    else  
     $count[$index] = $child; 
    $index++; 
    } 
    } 
    return $count; 
} 

請注意,它很難調試的代碼,因爲我沒有你的表。如果有任何錯誤讓我知道,我會解決它。 反正結果是數組 它應該包含索引指定級別的金額:

$result=display_children("Food", 0) ; 
var_export($result);//For exact info on all levels 
echo $result[0];//First level, will output 2 
echo $result[1];//Second level, will output 4 
echo $result[2];//Third level, will output 3 

而且通過有錯字在你的數據庫中,ID是10(牛肉),應該有父母「肉」,而不是這樣「垮掉「 我猜。

如果你想看測試頁面,其here

+0

感謝您的重播,但它的數組中的總輸出數組([] => 9)不等於 –

+0

這真的很奇怪,我在我的數據庫中製作了完全相同的表,並且按預期工作。也許有一些PHP版本不匹配,使數組值不工作,嘗試固定代碼 – Kyborek

+0

好吧我試着用那個 –

3
function display_children($parent, $level) 
{ 

$result = mysql_query('SELECT title FROM tree '.'WHERE parent="'.$parent.'"'); 
$count = ""; 
    while ($row = mysql_fetch_array($result)) 
    { 
    $data= str_repeat(' ',$level).$row['title']."\n"; 
    echo $data; 
    if($count!="") 
     $count .= (1 + $this->display_children($row['title'], $level+1)); 
    else 
     $count = ", ".(1 + $this->display_children($row['title'], $level+1)); 
    } 
    return $count; 
} 

我們來試試這個曾經..

+0

感謝重播,但代碼不工作,沒有給予計數 –

0

由PHP類的解決方案:

<?php 

class LevelDepCount{ 

    private $level_count=array(); 

    /** 
    * Display all child of an element 
    * @return int Count of element 
    */ 
    public function display_children($parent, $level, $isStarted=true) 
    { 
    if($isStarted) 
      $this->level_count=array(); // Reset for new ask 
    $result = mysql_query('SELECT title FROM tree '.'WHERE parent="'.$parent.'"'); 
    $count = 0; // For the level in the section 
     while ($row = mysql_fetch_array($result)) 
     { 
     $data= str_repeat(' ',$level).$row['title']."\n"; 
     echo $data; 
     $count += 1 + $this->display_children($row['title'], $level+1,false); 
     } 
     if(array_key_exists($level, $this->level_count)) 
      $this->level_count[$level]+=$count; 
     else 
      $this->level_count[$level]=$count; 
      return $count; 
    } 

    /** Return the count by level.*/ 
    public function getCountByLevel(){ 
     return $this->level_count; 
    } 

} 

$counter=new LevelDepCount(); 
$counter->display_children("Food",0); 
var_dump($counter->getCountByLevel()); 

?> 
1

article有所有你需要創建與MySQL一棵樹,以及如何通過水平

1

如果你不介意改變你的模式計算項目我有一個更簡單的替代解決方案。

你有像這樣的表你的約會......

item    id 
-------------+------ 
Food   | 1 
Fruit  | 1.1 
Meat   | 1.2 
Red Fruit | 1.1.1 
Green Fruit | 1.1.2 
Yellow Fruit | 1.1.3 
Pork   | 1.2.1 

查詢現在要簡單得多,因爲他們只是簡單的字符串操作。這對於少數幾百到幾千條條目很小的清單可以正常工作 - 它可能不會出色地擴展 - 我沒有嘗試過。

但是要計算第二級有多少事情,你可以做一個正則表達式搜索。

select count(*) from items 
where id regexp '^[0-9]+.[0-9]+$' 

第三個層次是剛剛

select count(*) from items 
where id regexp '^[0-9]+.[0-9]+.[0-9]+$' 

如果你只是想在一級支行2

select count(*) from items 
where id regexp '^[0-9]+.[0-9]+$' 
and id like "1.%" 

它,你並不需要運行許多優勢查詢數據庫,作爲獎勵,讀取表格中的數據並查看發生了什麼更容易。

我有一種嘮叨的感覺,這可能不被認爲是「好形式」,但它確實有效。我會對這種方法的批評非常感興趣,DB人員認爲這是一個很好的解決方案嗎?如果表格非常大,那麼一直進行表掃描和正則表達式會變得非常低效 - 您的方法會更好地使用任何索引,這就是爲什麼我說這可能不能很好地擴展,但是,需要運行這麼多的查詢,這可能是一個值得考慮的交易。

0

如果修改您的查詢就可以得到一舉所有數據並沒有那麼多的計算(未測試的代碼):

/* Get all the data in one swoop and arrange it for easy mangling later */ 
function populate_data() { 
    $result = mysql_query('SELECT parent, COUNT(*) AS amount, GROUP_CONCAT(title) AS children FROM tree GROUP BY parent'); 
    $data = array(); 
    while ($row = mysql_fetch_assoc($result)) { 
     /* Each node has the amount of children and their names */ 
     $data[$row['parent']] = array($row['children'], int($row['amount'])); 
    } 
    return $data; 
} 

/* The function that does the whole work */ 
function get_children_per_level($data, $root) { 
    $current_children = array($root); 
    $next_children = array(); 
    $ret = array(); 

    while(!empty($current_children) && !empty($next_children)) { 
     $count = 0; 
     foreach ($current_children as $node) { 
      $count += $data[$node][0]; /* add the amount */ 
      $next_children = array_merge($next_children, explode($data[$node][1])); /* and its children to the queue */ 
     } 
     ret[] = $count; 
     $current_children = $next_children; 
     $next_children = array(); 
    } 

    return $ret; 
} 

$data = populate_data(); 
get_children_per_level($data, 'Food'); 

它不應該是很難修改的功能,使每一個電話調用或每個級別調用一次來填充數據結構,而不將整個表格放入內存中。如果你的樹只有少數幾個孩子,那麼我會建議你不要這樣做,因爲一次獲得所有數據並計算它會更有效率。如果你有很多孩子的淺色樹木,那麼它可能是值得改變的。

也可以將所有內容放在一個函數中,但是當不需要重複調​​用時,我會避免重新計算數據。一個可能的解決方案是將它作爲一個類,使用populate_data函數作爲構造函數,將其作爲內部私有屬性存儲,並且使用與第一個參數相同的單一方法,因爲它會從其中獲取數據內部私人財產。

無論如何,我還建議您使用ID列作爲「父」引用而不是其他列。首先,如果任何名稱包含逗號,我的代碼將會中斷:P。此外,你可能有兩個不同的名稱相同的元素。例如,您可能有Vegetables -> Red -> PepperRed將與水果的Red一起下降。

要注意的另一件事是,如果您的數據庫數據不是樹,我的代碼將進入無限循環。如果圖中有任何循環,它將永遠不會完成。通過保留$visited陣列以及所有已經被訪問的節點並且不將它們推入環路內的$next_children陣列(可能使用array_diff($data[$node][1], $visited)