簡體   English   中英

在一年范圍內加入表時出現意外結果

[英]Unexpected result when joining a table in a year range

我正在與一個usersuser_rolespoint_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

問題

  • 為什么只返回2行而不是3行? 我選擇3年以內。
  • 如何將這些行的數量加在一起,以便獲得所有用戶的概述?

您未選擇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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM