我有一个聚合表和一个详细信息表,其中包含许多不同游戏的分数。详细信息表是数百万条记录,聚合表只包含每个游戏以及不同天数的平均分数。
例:
汇总表:
| ID | Name | AVG_SCORE_7_DAYS | AVG_SCORE_30_DAYS | ----------------------------------------------------- | 1 | Game 1| 10.3 | 20.3 | | 2 | Game 2| 14.3 | 26.3 |
详细表:
| ID | Name | Date | Score | -------------------------------------------- | 1 | Game 1| 2015-07-12 01:00:00 | 20 | | 2 | Game 2| 2015-07-12 01:00:00 | 26 | | 3 | Game 1| 2015-07-12 01:00:00 | 14 | | 4 | Game 2| 2015-07-12 01:00:00 | 9 |
我使用以下代码通过存储过程每晚更新我的聚合表:
UPDATE `aggregate` aggr
INNER JOIN
(
SELECT game_name, avg(score) AS avg_score
FROM `detail`
WHERE `date` BETWEEN (CURDATE() + INTERVAL -7 DAY) AND CURDATE()
GROUP BY `game_name`
) detail7 ON aggr.`game_name` = detail7.`game_name`
INNER JOIN
(
SELECT game_name, avg(score) AS avg_score
FROM `detail`
WHERE `date` BETWEEN (CURDATE() + INTERVAL -30 DAY) AND CURDATE()
GROUP BY `game_name`
) detail30 ON aggr.`game_name` = detail30.`game_name`
我遇到的问题是,如果7天,30天等某些游戏没有得分,则这些子查询不会返回任何记录,因此如果其中任何一个失败,那么该游戏的任何列都不会得到更新(由于内部联接)。有没有办法可以编写我的查询来更新其他列,即使子查询的结果没有返回任何结果?
答案 0 :(得分:2)
使用外部联接。您还可以简化逻辑,因此只需要一个聚合:
UPDATE `aggregate` aggr LEFT JOIN
(SELECT game_name,
avg(case when `date` BETWEEN (CURDATE() + INTERVAL -7 DAY) AND CURDATE() then score end) AS avg_score_07,
avg(case when `date` BETWEEN (CURDATE() + INTERVAL -30 DAY) AND CURDATE() then score end) AS avg_score_30
FROM `detail`
WHERE `date` BETWEEN (CURDATE() + INTERVAL -30 DAY) AND CURDATE()
GROUP BY `game_name`
) detail
ON aggr.`game_name` = detail.`game_name`
SET . . . ;