Im trying to count 2 different things from 2 different table with one query.
My problem is that one of my joins affects on the other join count.
I want each of the joins to count without any connection to the count from the other join.
Here is the query:
SELECT score.score, u.user_name,
COUNT(mrank.user_id) as rank, COUNT(cr.id) as completedChallenges
FROM user u
LEFT OUTER JOIN challenges_score_user_rel score
ON score.user_id = u.id AND score.challenge_group_id = 0
LEFT OUTER JOIN challenges_score_user_rel mrank
ON mrank.score >= score.score AND mrank.challenge_group_id = 0 AND (SELECT forGym.gym
FROM user forGym WHERE forGym.id = mrank.user_id) = 22
LEFT OUTER JOIN challenges_requests cr
ON u.id = cr.receiver AND cr.status = 3
WHERE u.gym = 22 AND score.score IS NOT NULL GROUP BY u.id ORDER BY score.score DESC LIMIT 20
+------------------+------+---------------------+
| score| user_name | rank | completedChallenges |
+------------------+------+---------------------+
| 999 | A | 3 | 3 |
+------------------+----------------------------+
| 155 | B | 2 | 0 |
+------------------+----------------------------+
| 130 | C | 3 | 0 |
+------------------+----------------------------+
| 24 | D | 4 | 0 |
+------------------+----------------------------+
As you can see from the results I get is that user A is in the first place but got rank 3.
The rank should be number in the ordered by score.
The count for the rank is from this join:
LEFT OUTER JOIN challenges_score_user_rel mrank
ON mrank.score >= score.score AND mrank.challenge_group_id = 0 AND (SELECT forGym.gym
FROM user forGym WHERE forGym.id = mrank.user_id) = 22
If I remove this join:
LEFT OUTER JOIN challenges_requests cr
ON u.id = cr.receiver AND cr.status = 3
The count is fine and I get the correct rank for the all the users.
Why does 2 joins affect each other can I make them count on they own?
The easiest way to solve this is to use count(distinct)
:
SELECT score.score, u.user_name,
COUNT(distinct mrank.user_id) as rank,
COUNT(distinct cr.id) as completedChallenges
The problem is that you are getting a cartesian product for each user. If the numbers are large, then this is not the best performing solution. In that case, you want to pre-aggregate the data in the from
clause or use a correlated subquery in the SELECT
clause.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.