2016-07-28 42 views
0

我目前的查询看起来像这样。我一直在试图优化它,但到目前为止我还没有运气。 我的目标是让每个玩家获得当日和前一天之间stat_value的差异,然后对其进行排序。 目前的代码工作正常,但我觉得没有优化。 The?值使用Java填充。跨多行优化MySQL查询

SELECT t1.stat_value - 
     (SELECT stat_value 
      FROM leaderheadsplayersdata_daily t2 
     WHERE t2.player_id = t1.player_id 
      AND t2.day = ? 
      AND t2.stat_type = ? 
     LIMIT 1 
     ) as sum 
    , (SELECT name 
      FROM leaderheadsplayers 
     WHERE leaderheadsplayers.player_id = t1.player_id 
     LIMIT 1 
     ) 
    FROM leaderheadsplayersdata_daily t1 
    WHERE day = ? 
    AND stat_type = ? 
    ORDER 
     BY sum DESC LIMIT 100 

表结构:

这是包含玩家ID和用户名的主表。

CREATE TABLE IF NOT EXISTS `leaderheadsplayers` 
(player_id INTEGER PRIMARY KEY AUTO_INCREMENT 
,uuid VARCHAR(36) NOT NULL UNIQUE 
,name VARCHAR(16) NOT NULL 
,last_join DATETIME 
) ENGINE = InnoDB 

这是包含日常数据的表格。

CREATE TABLE IF NOT EXISTS leaderheadsplayersdata_daily 
(player_id INTEGER NOT NULL 
,stat_value DOUBLE NOT NULL 
,stat_type VARCHAR(16) NOT NULL 
,day INTEGER NOT NULL 
,FOREIGN KEY (player_id) REFERENCES leaderheadsplayers(player_id) ON DELETE CASCADE 
,PRIMARY KEY(player_id, stat_type, day) 
) ENGINE = InnoDB 

在此先感谢

+0

描述你的表格结构将有助于建议回答 – evilpenguin

+0

新增数据库结构。 –

+0

你能提供在查询中使用EXPLAIN的输出吗? – ultrajohn

回答

1

因为你只有2天,你可以做的leaderheadsplayersdata_daily台双连接。

这将是这个样子:

SELECT 
    p.player_id, 
    p.name, 
    (dc.stat_value-dp.statvalue) AS difference, 
    dc.day, 
FROM leaderheadsplayers p 
JOIN leaderheadsplayersdata_daily dc ON p.player_id = dc.player_id 
JOIN leaderheadsplayersdata_daily dp ON p.player_id = dp.player_id and dp.day = (dc.day-1) 
WHERE dc.day = ?CURRENT_DAY? 
ORDER BY difference DESC 

dc代表 “当前日期”。 dp代表“以前的日期”。 p代表“玩家”。

为了获得良好性能,请在player_id(两个表中)和day列上添加索引。

对不起,我没有测试,没有ideea如果我有语法错误或东西。另外,请更换?CURRENT_DAY?与实际日期并添加其他条件WHERE条款,根据需要

如果ORDER BY difference DESC不工作,只是做ORDER BY (dc.stat_value-dp.statvalue) DESC

你有很多的子查询,你看起来像你可以看看一些documentation about JOINs。他们真的很有用。

+0

非常感谢。该查询现在非常快速。 –

+0

很高兴为您服务。 :) – evilpenguin

-1

或者,您可以尝试以下操作。让我知道这个版本如何使用隐式三重联接票价与上面提到的使用显式三重联接的票价。谢谢。

SELECT t3.player_id, improvement FROM 
    (SELECT t1.player_id as player_id, (t1.stat_value - t2.stat_value) as improvement 
     FROM leaderheadsplayersdata_daily t1 INNER JOIN leaderheadsplayersdata_daily t2 
     on t1.player_id = t2.player_id and t1.stat_type = t2.stat_type 
      and t2.day = ? and t1.day = ?) as t3 
    INNER JOIN leaderheadsplayers on 
     t3.player_id = leaderheadsplayers.player_id 
      ORDER BY improvement DESC LIMIT 100;