MySQL:获取多个条目的两个日期之间的变化百分比

时间:2016-12-26 03:48:08

标签: mysql sql

我试图获得表格中两个日期之间的变化百分比。我已将数据汇总到以下格式,但无法通过获取日期之间的差异。

当前输出:

+------------+---------+--------+
|    day     | player  | score  |
+------------+---------+--------+
| 2016-12-20 | player1 |  69253 |
| 2016-12-15 | player1 |  61662 |
| 2016-12-15 | player2 | 309180 |
| 2016-12-20 | player2 | 318112 |
| 2016-12-15 | player3 |   1525 |
| 2016-12-20 | player3 |   1405 |
+------------+---------+--------+

预期输出:

+---------+------------+------------+------------+----------+---------------+
| Player  | startDate  |  endDate   | startScore | endScore | percentChange |
+---------+------------+------------+------------+----------+---------------+
| player1 | 2016-12-15 | 2016-12-20 |      61662 |    69253 |        0.8904 |
| player2 | 2016-12-15 | 2016-12-20 |     309180 |   318112 |        0.9719 |
| player3 | 2016-12-15 | 2016-12-20 |       1525 |     1405 |       -0.0854 |
+---------+------------+------------+------------+----------+---------------+

我正在谈到这一点:

SET @maxDate = (SELECT DATE(from_unixtime(max(timestamp) /1000)) from city_data);
SET @minDate = date_sub(@maxDate, INTERVAL 5 day);

SELECT
    day,
    player,
    sum(score) as score
FROM
(
    SELECT
        DATE(FROM_UNIXTIME(cd.timestamp / 1000)) as day,
        player,
        score
    FROM
        city_data cd
    WHERE
        DATE(FROM_UNIXTIME(cd.timestamp / 1000)) IN(@minDate, @maxDate)
) t
GROUP BY
    day, player

我可以添加什么来查询以获得所需的输出?我想我们可以假设我的查询结果可以放入临时表并从那里使用?

编辑:按要求提供原始表格的示例(注意这只是一个示例,表格是几百万行)

---------------+--------------+-------+-----+
|   timestamp   |    player    | score |  id |
+---------------+--------------+-------+-----+
| 1477173600000 | player1      |    66 |   1 |
| 1477173600000 | player1      |   654 |   2 |
| 1477173600000 | player1      |     3 |     |
| 1477173600000 | player2      |   238 |   4 |
| 1477173600000 | player2      |  9123 |   5 |
| 1477287798758 | player1      |    69 |   6 |
| 1477287798758 | player1      |   678 |   7 |
| 1477287798758 | player1      |     8 |     |
| 1477287798758 | player2      |   698 |   9 |
| 1477287798758 | player2      | 11000 |  10 |
+---------------+--------------+-------+-----+

2 个答案:

答案 0 :(得分:1)

您可以使用:

<%= link_to 'About', pages_about_path %>

<%= link_to 'Contact', pages_contact_path %>

然后

--Created test table
create table t (day date, player varchar(100), score integer);
insert into t values ('2016-12-20','player1',  69253);
insert into t values ('2016-12-15','player1',  61662);
insert into t values ('2016-12-15','player2', 309180);
insert into t values ('2016-12-20','player2', 318112);
insert into t values ('2016-12-15','player3',   1525);
insert into t values ('2016-12-20','player3',   1405);

产生

1. Find the `max` and `min` of day for each player -- table alias `t2`
2. Join it twice with original table
    1. First on player and min of day from t2 --> to get minimum score
    2. Then on player and max of day from t2 --> to get maximum score
3. then, do a group by to actually calculate min and max of score.
4. find percentChange at the end.

select t.*, (endScore-startScore) / endScore percentChange
from (
select t1.player, t2.startDate, t2.endDate, min(t1.score) startScore, max(t3.score) endScore
from t t1
inner join
(select player, min(day) startDate, max(day) endDate
from t
group by player) t2
on t1.player = t2.player
and t1.day = t2.startDate
inner join t t3
on t2.player = t3.player
and t3.day = t2.endDate
group by t1.player, t2.startDate, t2.endDate) t;

答案 1 :(得分:1)

假设您需要每天及之前5天的分数比较,您可以使用self join

SELECT t1.player,
       t2.dt as startdate,
       t1.dt as enddate,           
       t2.score as startscore,
       t1.score as endscore,
       (t1.score-t2.score)/(1.0*t1.score) as pct_change
FROM (select player,DATE(FROM_UNIXTIME(timestamp / 1000)) as dt,sum(score) as score from city_data group by player,DATE(FROM_UNIXTIME(timestamp / 1000))) t1
JOIN (select player,DATE(FROM_UNIXTIME(timestamp / 1000)) as dt,sum(score) as score from city_data group by player,DATE(FROM_UNIXTIME(timestamp / 1000))) t2 
ON t1.player=t2.player AND DATE_SUB(t1.dt, INTERVAL 5 day) = t2.dt

如果您需要此结果集中的特定日期,则可以使用where子句对其进行过滤。例如,

SELECT * FROM (
SELECT t1.player,
       t2.dt as startdate,
       t1.dt as enddate,           
       t2.score as startscore,
       t1.score as endscore,
       (t1.score-t2.score)/(1.0*t1.score) as pct_change
FROM (select player,DATE(FROM_UNIXTIME(timestamp / 1000)) as dt,sum(score) as score from city_data group by player,DATE(FROM_UNIXTIME(timestamp / 1000))) t1
JOIN (select player,DATE(FROM_UNIXTIME(timestamp / 1000)) as dt,sum(score) as score from city_data group by player,DATE(FROM_UNIXTIME(timestamp / 1000))) t2 
ON t1.player=t2.player AND DATE_SUB(t1.dt, INTERVAL 5 day) = t2.dt
) x
WHERE startdate = date '2016-12-15' and enddate = date '2016-12-20'

说明:使用派生表获取每个玩家每天的得分总和。加入它两次,以便每位玩家每天加入前5天。之后,请参考表格并选择所需的值,以便它们位于同一行。