解決
クエリの例から、テーブル構造を単純化して、質問に答えるのに十分な情報を提供することができました。このソリューションを使用できます:
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
テーブルを選択する方法です。
サブカテゴリ ポイント (各親カテゴリごと)とそれぞれの親カテゴリのポイントの合計が必要なため、親カテゴリを垂直方向に追加してUNION
、基本的にそれ自体をサブカテゴリにすることができます。GROUP BY
これは、 andにうまく考慮され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
テーブル内の 2 つのフィールドを使用して、テーブルで自己相互参照結合を行いcategory_relations
ます。
category_relations
を使用せずにテーブルをそのまま結合した場合UNION
、結果の結合は次のようになります (列は簡略化されています)。
points_awarded ⋈ (links_from) category_relations ⋈ (links_to) points_awarded:
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
2 番目のpoints_amount
...
しかし待ってください。親カテゴリpoints_amount
も含める必要があります。どうすれば最初points_amount
のものを 2 番目のものに明確に入れることができるpoints_amount
でしょうか? ここで のUNION
出番です。
自己相互参照結合を実行する前に、category_relations
テーブルをサブ選択して少し変更します。
SELECT links_from, links_to FROM category_relations
UNION
SELECT links_from, links_from FROM category_relations
その結果、次のようになります。
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
基本的に、各親カテゴリをそれ自体のサブカテゴリにしました。この結果を結合で使用すると、次が生成されます。
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
れ、最初の をグループ化してcategory_id
2 番目を合計し(最初のカテゴリは無関係なので、この時点ではpoints_amount
無視します)、目的の出力を得ることができます。points_amount