[英]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.