2016-12-26 4 views
0

私のテーブルの2つの日付間の変更の割合を取得しようとしています。私は一緒にデータを次の形式にしましたが、日付の違いを得るために過去に移動することはできません。MySQL:複数のエントリの2つの日付の間の変更の割合を取得

電流出力:

+------------+---------+--------+ 
| 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 | 
+------------+---------+--------+ 

予想される出力:私は私のクエリに追加することができますどのような

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 

+---------+------------+------------+------------+----------+---------------+ 
| 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 | 
+---------+------------+------------+------------+----------+---------------+ 

私はこの時点に取得しています望ましいouを得るためにtput?私は私のクエリの結果が一時テーブルに入れてそこから使用できると仮定できると思いますか?

編集:要求ごと元のテーブルが(表は数万行で、これは単なる一例であることに注意)

---------------+--------------+-------+-----+ 
| 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 | 
+---------------+--------------+-------+-----+ 
+0

パーセント変化が正しくないようです – GurV

+0

これは私が手作業で行った出力の例ですが、オフになっている可能性があります。オフになっていると思われる値の例を教えてください。それにもかかわらず、私は視聴者が私が達成しようとしていることのアイデアを得ることができると確信しています。 編集:私はそこに後方に%を持っていました。 –

+0

元のテーブルを表示できますか? –

答えて

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' 

説明:1日あたり各プレイヤーのスコアの合計を取得するために、派生テーブルを使用してください。それを2倍にして、プレイヤーごとに毎日5日前に参加するようにします。その後、テーブルを参照し、同じ行になるように必要な値を選択します。

+0

うわー、それは素晴らしいです。 これらの結果を提供するために自己結合がどのように機能するかについて説明してください。私はそれの周りに私の頭を包み込むのは難しいです。 –

+0

@DouglasGaskell ..説明をチェックし、私に知らせてください。 –

+0

非常に良い!私はprettifiedとクエリを最適化した今私はそれがどのように動作するのか困惑している。実行時間は8秒から2秒です。ありがとう! –

1

あなたは、この使用することができますどのように見えるかの例:

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

は生成:

| player |     startDate |     endDate | startScore | endScore | percentChange | 
|---------|----------------------------|----------------------------|------------|----------|---------------| 
| player1 | December, 15 2016 00:00:00 | December, 20 2016 00:00:00 |  61662 | 69253 |  0.1096 | 
| player2 | December, 15 2016 00:00:00 | December, 20 2016 00:00:00 |  309180 | 318112 |  0.0281 | 
| player3 | December, 15 2016 00:00:00 | December, 20 2016 00:00:00 |  1525 |  1405 |  -0.0854 | 
+0

それは素晴らしい作品です!ただし、クエリのプロセスについていくつかの説明を追加できますか。私は解決策を得るのはうれしいですが、私はクエリの流れを理解することにもっと興味があります。 –

+0

@Douglas追加の説明 – GurV

関連する問題