2010-04-22 61 views
3

我在這裏有兩個關注表:users和race_weeks。用戶有很多race_weeks,race_week屬於User。因此,user_id是race_weeks表中的一個fk。SQL查詢數學體操

我需要在race_weeks表中的字段上執行一些具有挑戰性的數學運算,以便返回具有最多所有時間點的用戶。

以下是我們需要在race_weeks表中操作的字段。

races_won (int) 
races_lost (int) 
races_tied (int) 
points_won (int, pos or neg) 
recordable_type(varchar, Robots can race, but we're only concerned about type 'User') 

爲了讓您充分了解這裏工作的業務邏輯,用戶可以在一週內參加很多比賽。 race_week記錄代表該周用戶比賽的總結果。如果races_won,races_lost或races_tied大於0,則認爲該用戶在本週內處於活動狀態,否則用戶處於非活動狀態。

因此,這裏就是我們需要在我們的查詢工作要做,以便返回與最高分贏得用戶(實際上net_points_won):

  1. 計算每個用戶的net_points_won(而不是在數據庫字段)。

  2. 要計算net_points_won,需要(1000 * count_of_active_weeks) - sum(points__won)。 (爲什麼是1000?想象一下,每週用戶都會被發現有1000分可以參加比賽,我們希望將我們發現的用戶分解出來,因爲用戶每週只能輸入一次100分的比賽,坐在900,這究竟是誰贏得了最高分,我們會歪斜。)

這一個是有點令人費解,所以讓我知道如果我能進一步明確。

+0

在您嘗試解決之前,請查看我對Quassnoi的評論。 – keruilin 2010-04-22 17:05:24

回答

0

我相信,你的業務邏輯是不正確:net_points應該是贏得了用戶減分的用戶被發現的點數的總和。

此外,活動星期檢查應明確測試races_won,races_lostraces_tied,以使系統有機會在表變大時在這些列上使用索引。

SELECT user_id 
    , SUM(points_won) - 1000 * COUNT(*) AS net_points 
    FROM race_weeks 
WHERE recordable_type = 'User' 
    AND (races_won > 0 OR races_lost > 0 OR races_tied > 0) 
GROUP BY user_id 
ORDER BY net_points DESC 
+0

是的,你對商業邏輯絕對正確。 – keruilin 2010-04-22 19:46:39

0
SELECT user_id, 1000 * COUNT(*) - SUM(points_won) AS net_points 
FROM race_weeks 
WHERE races_won + races_lost + races_tied 
     AND recordable_type = 'User' 
GROUP BY 
     user_id 
ORDER BY 
     net_points DESC 
+0

如果用戶沒有參加某一週的比賽,那麼race_week表中仍會創建一條記錄。但是,races_won = 0,races_lost = 0和races_tied = 0。這就是我們如何判斷用戶是否處於非活動狀態。所以我們不能計算所有的race_week記錄。我們只能算有效的。 – keruilin 2010-04-22 17:01:51

+0

@keruilin:我將bot測試加入了WHERE條件。對於活躍用戶,'races_won + races_lost + races_tied'是'MySQL'中races_won + races_lost + races_tied <> 0'的快捷方式,因此只有活動用戶纔會被選中。 – Quassnoi 2010-04-22 17:18:28

+0

dang,你聰明! – keruilin 2010-04-22 17:20:51