2015-01-04 41 views
1

我試圖找到任何方法來優化這種說法:MySQL的優化嵌套SELECT和INSERT語句

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(量))的人也沒有成就(nick not 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

我會擺脫「WHERE NOT IN」,而是使用「LEFT JOIN [...]在那裏ISNULL」,因爲它快得多 – valicu2000

+0

@ valicu2000你能解釋一下嗎?我不知道如何制定這個聲明。 –

+0

是這樣的:INSERT INTO成就 ( 缺口,成本,achievement_type,announced_in_chat,shown_on_stream,DT ) ( SELECT p.nick,2000,0,TRUE,FALSE,NOW() FROM points_log p LEFT JOIN 成就 ON p.nick = a.nick WHERE a.nick ISNULL AND a.achievement_type = 0 AND a.stream_online = TRUE ) GROUP BY缺口HAVING SUM(量)> = 2 000; – valicu2000

回答

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上的索引。

索賠在你只是想避免在achievementsnick成就的問題。做最簡單的方法是是查詢:

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); 

然而,查詢有你的問題沒有解決的附加條件。