Reputation: 6344
I need help to formulate a query to calculate points based on user action. There is a user table which stores user info and each user belongs to a specific category (User category). Each category has different levels (say level1, level2 etc..) and each level has a set of tasks(Task1,Task2...) to be completed. Each task can be performed multiple times. But points is calculated based on a maximum limit field.
Task 1 - 10 points ( Max:2 - Means user can perform this task N times but for point calculation it will be only counted twice )
Task 2 - 5 points ( Max:1 )
For example lets say User1 performs Task1 5 times, but for point calculation Task1 will only be counted 2 times , so total points is 20. This is similar for all tasks.
On completing each task the user gains N points and get upgraded to next level. Please find below the table structure and query:
uid , uname , uc_id ( References User Category ) , ul_id (References user level and indicates current level of user )
uc_id ....
ul_id, uc_id (References User Category) ...
lt_id , ul_id (References User level) , lt_point, lt_max
ut_id, lt_id (References level task), uid (References user)
The below is the query i have tried so far :
SELECT uid, SUM(LT.lt_point/LT.lt_max) as TotalLevelPoints
FROM users AS U
INNER JOIN user_tasks AS UT ON UT.ut_user_id = U.id
INNER JOIN level_tasks AS LT ON LT.lt_id = UT.lt_id
INNER JOIN user_level AS UL ON UL.ul_id = LT.ul_id
INNER JOIN user_category AS UC ON UC.uc_id = UL.uc_id
WHERE UT.ut_status = 1 AND U.uid = 1 AND UL.ul_id = 1
GROUP BY U.uid
This gives all the sum without considering the max limit, how should i write so that sum is calculated on that column also. Hope my question is clear enough.. Any help would be really appreciated.
Upvotes: 1
Views: 92
Reputation: 160
There is some discrepancy between column names in schema and query you have provided. I have gone with schema.
Query is not tested. But this approach should work.
SELECT uid, SUM(LevelPoints) TotalLevelPoints
FROM ( SELECT U.uid, LT.lt_id, SUM((CASE WHEN COUNT(*) > lt_max THEN lt_max ELSE COUNT(*) END)*lt_point) LevelPoints
FROM users U
INNER JOIN user_tasks UT
ON U.uid = UT.uid
INNER JOIN level_tasks LT
ON UT.lt_id = LT.lt_id
GROUP BY U.uid, LT.lt_id
)
GROUP BY uid
Upvotes: 0
Reputation: 35623
I believe you will need to do this in 2 steps. First sum the points and compare to the maximums allowed for each task type. Once that is determined, sum those results for each user. e.g.
SELECT
u.uid
, SUM(user_task_points) AS user_task_points
FROM users AS u
INNER JOIN (
SELECT
ut.UT_user_id
, lt_id
, lt.LT_point
, lt.LT_max_times
, CASE WHEN SUM(lt.LT_point) > (lt.LT_point * lt.LT_max_times) THEN (lt.LT_point * lt.LT_max_times)
ELSE SUM(lt.LT_point)
END AS user_task_points
FROM user_tasks AS ut
INNER JOIN level_tasks AS lt ON ut.UT_rule_id = lt.LT_id
INNER JOIN user_level AS UL ON UL.ul_id = LT.ul_id
WHERE ut.UT_status = 1
AND ut.UT_user_id = 1
AND ul.ul_id = 1
GROUP BY
ut.UT_user_id
, lt_id
, lt.LT_point
, lt.LT_max_times
) AS p ON u.id = p.UT_user_id
GROUP BY
u.uid
;
Upvotes: 2