Calculate monthly userscores between two tables using MySQL?
Pergunta
I found a lot of helpful information on stackoverflow, but a tiny bit is still missing to solve the following issue:
I have two tables userscores and userpoints like that:
#table userscores (saves userpoints each month)
date userid points
2012-05-01 1 23
2012-06-01 1 34
#table userpoints (recent points)
userid points
1 23
2 10
3 15
I was able to find out how to calculate the differences between recent userpoints and stored userpoints (from table "userscores") of the current month using:
SELECT userpoints.userid, userpoints.points - userscores.points AS mpoints
FROM `userpoints`,`userscores`
WHERE userpoints.userid=userscores.userid
AND YEAR(userscores.date) = YEAR(CURDATE())
AND MONTH(userscores.date) = MONTH(CURDATE())
AND userpoints.userid != ".$adminID."
ORDER BY mpoints DESC;"
However, this query is only comparing the userid from both tables and ignoring the userids that exist in table userpoints and but do not exist in table userscores.
The query should be modified so that newly created userids (in table userpoints) are considered as scores as well.
I found out how to query to get the userids that do not exist in table userscores:
SELECT userpoints.userid FROM `userpoints`
WHERE userpoints.userid
NOT IN(SELECT qa_userscores.userid FROM `qa_userscores`)
Now I have to combine both but trying the following does not work:
SELECT userpoints.userid, userpoints.points - userscores.points AS mpoints
FROM `userpoints`,`userscores`
WHERE (
userpoints.userid = userscores.userid
AND YEAR(userscores.date) = YEAR(CURDATE())
AND MONTH(userscores.date) = MONTH(CURDATE())
AND userpoints.userid != ".$adminID."
)
OR (
userpoints.userid IN(SELECT userpoints.userid FROM `userpoints`
WHERE userpoints.userid
NOT IN(SELECT DISTINCT userscores.userid FROM `userscores`))
)
ORDER BY mpoints DESC;
Any help appreciated.
Solução
SELECT userpoints.userid, userpoints.points - coalesce(userscores.points,0)
AS mpoints
FROM `userpoints`
left join `userscores` on userpoints.userid=userscores.userid
AND YEAR(userscores.date) = YEAR(CURDATE())
AND MONTH(userscores.date) = MONTH(CURDATE())
where userpoints.userid != ".$adminID."
ORDER BY mpoints DESC;"
The Left join automatically retains the rows on the left side even when there is no corresponding row on the right. All conditions you check on the right side must be in the Join Condition. Finally, you need to use a default value for the Right Side value when ther is none.
Outras dicas
You can combine the results from two queries using UNION
.
SELECT userpoints.userid, userpoints.points - userscores.points AS mpoints
FROM `userpoints`,`userscores`
WHERE userpoints.userid=userscores.userid
AND YEAR(userscores.date) = YEAR(CURDATE())
AND MONTH(userscores.date) = MONTH(CURDATE())
UNION
SELECT userpoints.userid, points as mpoints FROM `userpoints`
WHERE userpoints.userid
NOT IN(SELECT userscores.userid FROM `userscores`)
See the mysql documentation for more information on the usage of UNION
.