跨多行优化MySQL查询

时间:2016-07-28 13:47:42

标签: mysql optimization

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

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

提前致谢

2 个答案:

答案 0 :(得分: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添加索引。

抱歉,我没有测试,如果我有语法错误或其他东西,请不要。另外,请将?CURRENT_DAY?替换为实际日期,并根据需要在WHERE子句中添加其他条件

如果ORDER BY difference DESC不起作用,请执行ORDER BY (dc.stat_value-dp.statvalue) DESC

你有很多子查询,看起来你可以看一些documentation about JOINs。它们非常有用。

答案 1 :(得分:-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;