简体   繁体   English

跨多行优化MySQL查询

[英]Optimizing MySQL query across multiple rows

my current query looks something like this. 我当前的查询看起来像这样。 I've been trying to optimize it but I got no luck so far. 我一直在尝试优化它,但到目前为止我还没有运气。 My goal is to get the difference in stat_value between the current day and the previous day for every player and then order it. 我的目标是获取每个玩家在当前日期和前一天之间的stat_value差异,然后对其进行排序。 The current code works fine, but feels unoptimized to me. 当前的代码工作正常,但对我来说却没有优化。 The ? values are filled in using Java. 值使用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

Table structure: 表结构:

This is the main table containing the player id and username. 这是包含玩家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

This is the table containing the daily data. 这是包含每日数据的表。

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

Thanks in advance 提前致谢

Because you only have 2 days, you can do a double join on the leaderheadsplayersdata_daily table. 由于您只有2天的时间,因此可以对leaderheadsplayersdata_daily表进行两次leaderheadsplayersdata_daily

It would look something like this: 它看起来像这样:

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 stands for "date current". dc代表“日期电流”。 dp stands for "date previous". dp代表“上一个日期”。 p stands for "player". p代表“玩家”。

For good performance, add indexes on the columns player_id (in both tables) and day . 为了获得良好性能,请在player_id (在两个表中)和day列上添加索引。

Sorry, I didn't test, have not ideea if I have syntax errors or stuff. 抱歉,我没有测试,如果我有语法错误或其他东西,还没有想法。 Also, please replace ?CURRENT_DAY? 另外,请替换?CURRENT_DAY? with the actual day and add other conditions in WHERE clause, as needed 与实际日期并根据需要在WHERE子句中添加其他条件

If ORDER BY difference DESC does not work, just do ORDER BY (dc.stat_value-dp.statvalue) DESC . 如果ORDER BY difference DESC不起作用,则只需执行ORDER BY (dc.stat_value-dp.statvalue) DESC

You have a lot of subqueries, you look like you could take a look at some documentation about JOINs . 您有很多子查询,看起来您可以看一下有关JOIN的一些文档 They're really useful. 它们真的很有用。

Alternatively, you can try the following. 或者,您可以尝试以下方法。 Let me know how this version that uses implicit triple join fare with the one suggested above that uses explicit triple join. 让我知道这个使用隐式三联票价的版本和上面建议的使用显式三联票价的版本。 Thanks. 谢谢。

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;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM