我目前正在使用积分系统,该系统使用下面的查询列出一个类别或其下方任何类别中得分最多的人(使用'category_relations表'中的'links_to'和'links_from')。< / p>
SELECT u.name,
pa.user_id,
SUM(IF(pa.plus = '1', pa.points_amount, 0)) -
SUM(IF(pa.plus = '0', pa.points_amount, 0)) AS points
FROM points_awarded pa, Users u
WHERE u.user_id = pa.user_id AND
(
category_id = '" . $category_id . "' OR
category_id IN
(
SELECT links_to
FROM category_relations
WHERE links_from = '" . $category . "'
)
)
GROUP BY user_id
ORDER BY points DESC
LIMIT 50
我现在要做的是切换此查询以查找特定用户的所有类别,而不是查找特定类别的所有用户。以下是我尝试使用的查询,但这只包括该类别的点,而不是下面的子类别。
SELECT u.name,
pa.user_id,
pa.category_id,
SUM(IF(pa.plus = '1', pa.points_amount, 0)) -
SUM(IF(pa.plus = '0',pa.points_amount, 0)) AS points
FROM points_awarded pa, Users u
WHERE u.user_id = pa.user_id AND
u.user_id = '" . $user_id . "'
GROUP BY pa.category_id
ORDER BY points DESC
LIMIT 50
答案 0 :(得分:5)
从您的示例查询中,我能够推导出表结构的简化,这为我提供了足够的信息来回答您的问题。您可以使用此解决方案:
SELECT a.user_id,
a.name,
b.category_id,
SUM(IF(d.plus = '1', d.points_amount, 0)) -
SUM(IF(d.plus = '0', d.points_amount, 0)) AS points
FROM Users a
JOIN points_awarded b ON a.user_id = b.user_id
JOIN (
SELECT links_from, links_to
FROM category_relations
UNION
SELECT links_from, links_from
FROM category_relations
) c ON b.category_id = c.links_from
JOIN points_awarded d ON c.links_to = d.category_id
WHERE a.user_id = $user_id
GROUP BY a.user_id,
a.name,
b.category_id
ORDER BY points DESC
LIMIT 50
其中$user_id
是查询的用户ID参数。
基本上,此查询的关键组件是我们选择category_relations
表的方式。
由于你想要子类别点的总和(按每个父类别) 加上 它们各自的父类别的点数,我们可以通过{{1}垂直增加父类别并且基本上使它成为自身的子类别。这将很好地考虑到UNION
和GROUP BY
。
假设我们有一些(简化的)数据:
SUM
Users
------------------
user_id | name
433 | Zane
points_awarded
------------------
user_id | category_id | plus | points_amount
433 | 1 | 1 | 785
433 | 2 | 1 | 871
433 | 3 | 1 | 236
433 | 4 | 0 | 64
433 | 5 | 0 | 12
433 | 7 | 1 | 897
433 | 8 | 1 | 3
433 | 9 | 0 | 48
433 | 10 | 1 | 124
433 | 14 | 0 | 676
为了区分父类和子类,查询使用category_relations
------------------
links_from | links_to
1 | 2
1 | 3
1 | 4
5 | 8
5 | 9
7 | 10
7 | 14
表中的两个字段在points_awarded
表上进行自交叉引用连接。
如果我们刚刚加入category_relations
表而没有category_relations
,那么我们的结果将会像(简化列)一样:
UNION
如您所见,最左侧的category_id | points_amount | category_id | points_amount
1 | 785 | 2 | 871
1 | 785 | 3 | 236
1 | 785 | 4 | 64
5 | 12 | 8 | 3
5 | 12 | 9 | 48
7 | 897 | 10 | 124
7 | 897 | 14 | 676
是父类别,最右侧的category_id
是相应的子类别。我们可以轻松地对第一个category_id和category_id
第二个SUM
...
但是等等,我们还需要包含父类别'points_amount
!我们如何将第一个points_amount
明显地放入第二个points_amount
?这是points_amount
发挥作用的地方。
在我们执行自我交叉引用连接之前,我们先选择UNION
表,以便稍微改变它:
category_relations
然后导致:
SELECT links_from, links_to FROM category_relations
UNION
SELECT links_from, links_from FROM category_relations
我们基本上将每个父类别作为其自身的子类别。我们在连接中使用this的结果,然后产生:
category_relations (subselected)
------------------
links_from | links_to
1 | 1 <-- parent category
1 | 2
1 | 3
1 | 4
5 | 5 <-- parent category
5 | 8
5 | 9
7 | 7 <-- parent category
7 | 10
7 | 14
在那里, NOW 将父类别纳入category_id | points_amount | category_id | points_amount
1 | 785 | 1 | 785
1 | 785 | 2 | 871
1 | 785 | 3 | 236
1 | 785 | 4 | 64
5 | 12 | 5 | 12
5 | 12 | 8 | 3
5 | 12 | 9 | 48
7 | 897 | 7 | 897
7 | 897 | 10 | 124
7 | 897 | 14 | 676
,我们现在可以对第一个SUM
进行分组,对第二个进行汇总{ {1}}(此时忽略第一个category_id
,因为它无关紧要),为您提供所需的输出。
答案 1 :(得分:2)
我很确定加入category_relations表有一种更简单的方法可以做到这一点,但很难看不到表格的任何可视化例子......我认为这应该有效:
SELECT u.name
,pa.user_id
,pa.category_id,
SUM(IF(pa.plus = '1', pa.points_amount, 0)) - SUM(IF(pa.plus = '0',pa.points_amount, 0)) AS points
FROM points_awarded pa
JOIN Users u
USING (user_id)
WHERE category_id IN(
SELECT links_to
FROM category_relations
WHERE links_from = (
SELECT category_id
FROM points_awarded
WHERE user_id = '" . $user_id . "'
)
)
GROUP BY pa.category_id
ORDER BY points DESC
LIMIT 50
您没有在上面发布的示例中看到子类别,因为您没有包含category_relations表中的记录。我们使用子子查询来查找与用户关联的所有category_ids,而不是通过查询的category_id查找链接的类别。给这一点,如果这不对,请发布一些显示表格数据的小片段。