我有一张表跟踪用户的每日分数。看起来大致如下:
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
);
现在每天从球员历史数据中重新计算球员的加权得分。 我可以在几个通道中执行此操作,如下所示:
-- 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?
答案 0 :(得分:2)
使用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中可能没有记录。
答案 1 :(得分:1)
尝试使用LEFT JOIN
代替JOIN
,DEFAULT
设置为0
修改强>
LEFT JOIN
是您第一个问题的正确解决方案,第二个问题是您需要INSERT
- 解决此问题的最佳方法是使用INSERT
... ON DUPLICATE KEY UPDATE
,所以:
INSERT INTO table(cols) VALUES(values) ON DUPLICATE KEY UPDATE score=....