我们拥有用户,问题和无限级别的类别。用户可以从问题中获得一些积分。问题可以有多个类别。
我想要做的是计算每个类别的最高用户数:它只是从该类别下的问题中获取的总点数,也是它的子类别。
所以,我有这些表:
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分且 1分来自Rails。每个类别的此用户的积分将为:
Programming 11 (5+5+1)
PHP 5 (2+3)
Zend Framework 3
Symfony
Java 5
Ruby on Rails 1
答案 0 :(得分:1)
也许最好使用标签而不是层次结构。例如,任何带有" Zend Framework"还将拥有" PHP"和"编程"标签。当某些类别可以出现在多个位置时,这也会有所帮助。例如,我可以在jQuery和Javascript中使用ajax。然后,为用户的类别中列出的每个标记添加1。
答案 1 :(得分:0)
我会创建一个user_categories
表格,在其中我会存储3个值:user_id
,category_id
和user_score
。它易于维护(只需要INSERT
或UPDATE
),并且查询每个类别的最高用户也很容易。
答案 2 :(得分: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
答案 3 :(得分: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...
}