繁体   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