2012-07-16 233 views
0

我們有用戶,問題和無限級別的類別。用戶可以從問題中獲得一些觀點。問題可以有多個類別。樹遍歷遞歸計算

我想要做的是計算每個類別的最高用戶數:它只是從該類別下的問題中獲得的總點數,也是它的子類別。

所以,我有這些表:

questions 
-------------- 
id 
title 
question 

categories 
-------------- 
id 
parent_id 
category 
lft 
rgt 

question_categories 
-------------- 
question_id 
category_id 

users 
-------------- 
id 
username 

user_points 
-------------- 
id 
user_id 
question_id 
point_type 
points 

user_category 
-------------- 
user_id 
category_id 
points  

我想要做的是計算user_category.points值。 總結每個類別的要點很簡單,但包括子類別越來越複雜。

什麼可能是最好的方法來做到這一點?

計算的例子:

假設的類別是:

Programming 
    PHP 
     Zend Framework 
     Symfony 
    Java 
    Ruby on Rails 

假設用戶得到3分從Zend框架,2點從PHP,5分從Java和來自Rails的1分。每類此用戶的積分將是:

Programming   11 (5+5+1) 
    PHP     5 (2+3) 
     Zend Framework 3 
     Symfony 
    Java     5 
    Ruby on Rails  1 

回答

0

我會創造一個user_categories表,其中我將存儲3個值:user_idcategory_iduser_score。它很容易維護(只需要INSERTUPDATE),並且它也很容易查詢每個類別的最高用戶。

1

也許最好是使用標籤而不是層次結構。例如,任何帶有「Zend Framework」的東西都會有「PHP」和「Programming」標籤。這也有助於某些類別可以出現在多個地方。例如,我可以在jQuery和Javascript中使用ajax。然後,爲該用戶的類別中列出的每個標籤添加1。

0

如果您只計算每個頂級類別的總和,那麼您應該在名爲root_id的類別表中添加一個字段(保存該類別的傳遞父級的ID)。

那麼你的總和將被計算爲:

select up.user_id, ctg.root_id, sum(up.points) 
from user_points up 
join question_categories qc on up.question_id = qc.question_id 
join categories ctg on qc.category_id = ctg.id 
group by up.user_id, ctg.root_id 
0

這個PHP和SQL應該讓你的前3名用戶爲每個類別包括子類:

$query = "SELECT id, parent_id FROM categories"; 
$parent = array(); 
...fetch mysql data loop depending on what connection you use, mysqli or pdo... 
{ 
    $parent[$result['id']] = $result['parent_id']; 
} 

$childs = array(); 

foreach($parent as $id => $parrent_id) 
{ 
    $childs[$parrent_id][$id] = $id; 
    $next_parrent_id = $parrent_id; 
    while($next_parrent_id = $parent[$next_parrent_id]) 
    { 
     $childs[$next_parrent_id][$id] = $id; 
    } 
} 

foreach($parent as $id => $parrent_id) 
{ 
    $current_categories = array($id => $id) + $childs[$id]; 
    $query = "SELECT user_id, username, SUM(points) AS total_points 
      FROM user_points 
      LEFT JOIN users ON (user_id = users.id) 
      LEFT JOIN question_categories USING (question_id) 
      WHERE category_id IN (" . implode(', ', $current_categories). ") 
      ORDER BY total_points DESC 
      LIMIT 3"; 
    ...fetch mysql data loop... 
}