我正试图找到任何方法来优化这个陈述:
INSERT INTO achievements
(
nick, cost, achievement_type, announced_in_chat, shown_on_stream, dt
)
SELECT nick, 2000, 0, TRUE, FALSE, NOW()
FROM points_log
WHERE nick NOT IN
(
SELECT nick from achievements
WHERE achievement_type = 0 AND stream_online = TRUE
)
GROUP BY nick HAVING SUM(amount) >= 2000;
目标是找到从points_log获得2000分(SUM(金额))并且也不在成就中的人(不是IN)。任何帮助将不胜感激。
以下是成就和points_log表:
mysql> describe achievements;
+-------------------+-----------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------------+-----------------------+------+-----+---------+----------------+
| id | mediumint(8) unsigned | NO | PRI | NULL | auto_increment |
| nick | char(25) | NO | PRI | NULL | |
| cost | decimal(8,4) | NO | MUL | NULL | |
| achievement_type | tinyint(3) unsigned | NO | MUL | NULL | |
| announced_in_chat | tinyint(1) | NO | | NULL | |
| shown_on_stream | tinyint(1) | NO | | NULL | |
| dt | datetime | NO | PRI | NULL | |
+-------------------+-----------------------+------+-----+---------+----------------+
7 rows in set (0.01 sec)
mysql> describe points_log;
+-------------------+-----------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------------+-----------------------+------+-----+---------+----------------+
| id | mediumint(8) unsigned | NO | PRI | NULL | auto_increment |
| nick | char(25) | NO | PRI | NULL | |
| amount | decimal(10,4) | YES | MUL | NULL | |
| stream_online | tinyint(1) | NO | MUL | NULL | |
| modification_type | tinyint(3) unsigned | NO | MUL | NULL | |
| dt | datetime | NO | PRI | NULL | |
+-------------------+-----------------------+------+-----+---------+----------------+
6 rows in set (0.01 sec)
答案 0 :(得分:1)
优化insert
实际上只是优化查询:
SELECT nick, 2000, 0, TRUE, FALSE, NOW()
FROM points_log
WHERE nick NOT IN (SELECT nick
from achievements
WHERE achievement_type = 0 AND stream_online = TRUE
)
GROUP BY nick
HAVING SUM(amount) >= 2000;
我可能会将这个问题“彻底改变”:
SELECT pl.nick, 2000, 0, TRUE, FALSE, NOW()
FROM points_log pl LEFT JOIN
achievements a
ON a.nick = pl.nick AND a.achievement_type = 0 AND a.stream_online = TRUE
WHERE a.nick IS NULL
GROUP BY nick
HAVING SUM(amount) >= 2000;
对于此查询,您需要achievements(nick, achievement_type, stream_online
上的索引。
您声明在问题中,您只是想避免nick
中achievements
的成就。 的最简单方法是使用查询:
INSERT INTO achievements(nick, cost, achievement_type, announced_in_chat, shown_on_stream, dt)
SELECT pl.nick, 2000, 0, TRUE, FALSE, NOW()
FROM points_log pl
GROUP BY nick
HAVING SUM(amount) >= 2000
ON DUPLICATE KEY SET nick = VALUES(nick);
一个独特的索引:
CREATE UNIQUE INDEX idx_achievements_nick ON achievements(nick);
但是,您的查询还有其他问题无法解决的问题。