我正在使用users
,user_roles
和point_standards
。用户需要根据自己的角色在一定时期内达到一定的目标。从特定年份完成的课程中获取积分。检索用户点不是问题。
对于用户必须达到的某些点,定义了一个标准。这些都是3年,不能重叠。请参见下面的示例。
这意味着,从2018年到2020年,具有分配给这些条件的角色的用户需要达到93分。
2018年,用户应获得31分(93/3)。
问题是当用户想要检查与更多条件相对应的年份的条件时。假设用户要检查2018、2017和2016年的条件。这意味着:
(93 / 3) + (50 / 3) + (50 / 3)
以这些总和为上限时,这将导致2018年,2017年和2016年的标准为65分。
对于我的最终预期结果,我希望获得所有用户的概述以及特定年份的标准。
在下面的示例中,我试图检索单个用户在2018、2017和2016年的条件。
SELECT `users`.first_name,
ps.points
FROM `users`
# Join the user roles table
INNER JOIN `user_roles`
ON `users`.`role_id` = `user_roles`.`id`
# Get the criteria for 2018, 2017 and 2016
LEFT JOIN (SELECT id, role_id, COALESCE(points / 3) AS points
FROM point_standards
WHERE 2018 BETWEEN YEAR(start_year) AND YEAR(end_year)
OR 2017 BETWEEN YEAR(start_year) AND YEAR(end_year)
OR 2016 BETWEEN YEAR(start_year) AND YEAR(end_year)) ps
ON (user_roles.id = ps.role_id)
WHERE users.id = 123
GROUP BY `users`.`id`, ps.id
ORDER BY `points_internal` DESC
这将导致2行具有正确的条件。
预期结果
在这种情况下,它应该返回3行。这是因为我想查看2018、2017和2016年的标准。
然后我希望可以为每个用户对这3行中的points
求和。
问题
答案 0 :(得分:1)
您没有选择3行,而是选择了至少包含2016、2017、2018年其中之一的所有行,而这些行中恰好有两行(表中的前两行)。
如果要为这三种情况中的每种情况分别使用行,则可以为每种情况编写一个子查询,并对它们执行UNION ALL
。所以不用写
SELECT id, role_id, COALESCE(points / 3) AS points
FROM point_standards
WHERE 2018 BETWEEN YEAR(start_year) AND YEAR(end_year)
OR 2017 BETWEEN YEAR(start_year) AND YEAR(end_year)
OR 2016 BETWEEN YEAR(start_year) AND YEAR(end_year)
您使用
SELECT id, role_id, COALESCE(points / 3) AS points
FROM point_standards
WHERE 2018 BETWEEN YEAR(start_year) AND YEAR(end_year)
UNION ALL
SELECT id, role_id, COALESCE(points / 3) AS points
FROM point_standards
WHERE 2017 BETWEEN YEAR(start_year) AND YEAR(end_year)
UNION ALL
SELECT id, role_id, COALESCE(points / 3) AS points
FROM point_standards
WHERE 2016 BETWEEN YEAR(start_year) AND YEAR(end_year)
如果您有一个从中获取年份的表,则可以与此表执行联接,这比较省事。
编辑:整个查询应如下所示:
SELECT `users`.first_name,
ps.points
FROM `users`
# Join the user roles table
INNER JOIN `user_roles`
ON `users`.`role_id` = `user_roles`.`id`
# Get the criteria for 2018, 2017 and 2016
LEFT JOIN (
SELECT id, role_id, COALESCE(points / 3) AS points
FROM point_standards
WHERE 2018 BETWEEN YEAR(start_year) AND YEAR(end_year)
UNION ALL
SELECT id, role_id, COALESCE(points / 3) AS points
FROM point_standards
WHERE 2017 BETWEEN YEAR(start_year) AND YEAR(end_year)
UNION ALL
SELECT id, role_id, COALESCE(points / 3) AS points
FROM point_standards
WHERE 2016 BETWEEN YEAR(start_year) AND YEAR(end_year)
) ps
ON (user_roles.id = ps.role_id)
WHERE users.id = 123
GROUP BY `users`.`id`, ps.id
ORDER BY `points_internal` DESC
或更短一点(通过创建自己的years
子查询):
SELECT `users`.first_name,
ps.points
FROM `users`
# Join the user roles table
INNER JOIN `user_roles`
ON `users`.`role_id` = `user_roles`.`id`
# Get the criteria for 2018, 2017 and 2016
LEFT JOIN (
SELECT id, role_id, COALESCE(points / 3) AS points
FROM point_standards
JOIN (SELECT 2016 AS y UNION SELECT 2017 AS y UNION SELECT 2018 AS y) years
ON years.y BETWEEN YEAR(start_year) AND YEAR(end_year)
) ps
ON (user_roles.id = ps.role_id)
WHERE users.id = 123
GROUP BY `users`.`id`, ps.id
ORDER BY `points_internal` DESC