[英]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_id
, category_id
和user_score
。 它易於維護(僅需要INSERT
或UPDATE
),也易於查詢每個類別的頂級用戶。
如果只想對每個頂級類別進行匯總,則應在類別表中添加一個名為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.