簡體   English   中英

樹遍歷遞歸計算

[英]Tree Traversal recursive calculation

我們有用戶,問題和無限級別的類別。 用戶可以從問題中得到一些要點。 問題可以有多個類別。

我要做的是計算每個類別的最高用戶:這只是該類別下的問題及其子類別的總分。

所以,我有這些表:

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

假設用戶從Zend Framework獲得3分 ,從PHP獲得2分 ,從Java獲得5分 ,從Rails獲得1分 該用戶每個類別的分數將是:

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

也許最好使用標簽而不是層次結構。 例如,任何帶有“ Zend Framework”的東西也將帶有“ PHP”和“ Programming”標簽。 當某些類別可以出現在多個位置時,這也有幫助。 例如,我可以在jQuery和Javascript中使用ajax。 然后,為用戶類別中列出的每個標簽添加1。

我將創建一個user_categories表,其中將存儲3個值: user_idcategory_iduser_score 它易於維護(僅需要INSERTUPDATE ),也易於查詢每個類別的頂級用戶。

如果只想對每個頂級類別進行匯總,則應在類別表中添加一個名為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

此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...
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM