2012-07-17 112 views
2

我有一個表跟蹤每個用戶的日常分數。它看起來大致是這樣的:如何做一個缺省行的缺省值的mysql連接

CREATE TABLE `DailyScores` (
    `player_id` INTEGER NOT NULL, 
    `day_id` INTEGER NOT NULL, 
    `score` DOUBLE NOT NULL 
); 

我也有一個球員表看起來像這樣:

CREATE TABLE `Players` (
    `player_id` INTEGER NOT NULL, 
    `weighted_score` DOUBLE NOT NULL 
); 

現在weighted_score是球員從球員的歷史數據重新計算每天。 我可以通過幾個步驟做到這一點,是這樣的:

-- Clear out the old values 
UPDATE Players SET Players.weighted_score = 0; 

-- Then several times with different @weight and @day values 
UPDATE Players p JOIN DailyScores ds 
    ON p.player_id = ds.id 
    WHERE ds.day_id = @day 
    SET p.weighted_score = p.weighted_score + @weight * ds.score; 

此處理,有可能是一個天,一個球員沒有一個得分進入的情況。

不過,我想重寫UPDATE更是這樣的:

UPDATE Players p 
    JOIN DailyScores ds1 ON p.player_id = ds1.id 
    JOIN DailyScores ds2 ON p.player_id = ds2.id 
    JOIN DailyScores ds3 ON p.player_id = ds3.id 
    WHERE 
    ds1.day_id = @day1 AND 
    ds2.day_id = @day2 AND 
    ds3.day_id = @day3 
    SET p.weighted_score = @w1 * ds1.score + @w2 * ds2.score + @w3 * ds3.score; 

但我認爲,如果有一個丟失的分數,這將失敗。無論如何要讓缺失的日子的值爲0?

回答

1

使用COALESCE()函數。它返回的第一個參數不是NULL

UPDATE Players p 
    LEFT JOIN DailyScores ds1 ON (p.player_id = ds1.id AND ds1.day_id = @day1) 
    LEFT JOIN DailyScores ds2 ON (p.player_id = ds2.id AND ds2.day_id = @day2) 
    LEFT JOIN DailyScores ds3 ON (p.player_id = ds3.id AND ds3.day_id = @day3) 
    SET p.weighted_score = 
    @w1 * COALESCE(ds1.score, 0) + 
    @w2 * COALESCE(ds2.score, 0) + 
    @w3 * COALESCE(ds3.score, 0); 

你也需要做一個LEFT JOIN,因爲有可能是在DailyScores沒有記錄,當球員沒有發揮。

+0

已修復,以便它實際上行爲正確。 – 2012-08-07 07:22:52

1

嘗試使用LEFT JOIN代替JOINDEFAULT設置爲0

編輯

LEFT JOIN是你的第一個問題的正確解決方案,第二個你需要一個INSERT - 的最佳途徑要解決此是使用INSERT ... ON DUPLICATE KEY UPDATE,所以:

INSERT INTO table(cols) VALUES(values) ON DUPLICATE KEY UPDATE score=....