[英]Unexpected result when joining a table in a year range
我正在與一個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
。
問題
您未選擇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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.