按类别汇总最近N个以前的条目

时间:2015-03-14 02:18:57

标签: mysql sql greatest-n-per-group

我有一张桌子,我试图汇总最近N个值的值。在MSSQL中,您可以引用子查询中的外部表,但不能在mysql中引用外部表,因此我试图找出另一种方法来执行此操作。这是我正在使用的超简化版本:

gameid, teamid, gamedate, total
===============================
g1, A, 1/1/15, 1
g1, B, 1/1/15, 2
g2, A, 1/2/15, 3
g2, C, 1/2/15, 4
g3, B, 1/3/15, 5
g3, C, 1/3/15, 6
...
...
g5, A, 1/5/15, 7
...
g8, A, 1/8/15, 8
g8, B, 1/8/15, 9

作为一个例子,让我们说每个游戏/团队组合我想要平均团队所玩的最后2场比赛。对于前面的示例,输出看起来像这样(带有一些评论)

gameid, teamid, AVG(total)
==========================
g1, A, NULL  <--- No games before this
g1, B, NULL
g2, A, 1.0   <--- Only one game before this
g2, C, NULL
g3, B, 2.0
g3, C, 4.0
...
g5, A, 2.0   <---- Two games before this
...
g8, A, 5.0   <---- Three games before this, only average last 2

我可以像这样加入桌子,获得以前所有游戏的平均值,但我不知道如何将其限制在最近的N场比赛中:

SELECT g.gameid, g.teamid, g.gamedate, AVG(g1.total)
  FROM games g
  JOIN
       (SELECT teamid, gamedate, total
          FROM games) g1 ON g1.teamid = g.teamid
 WHERE g1.gamedate < g.gamedate
 GROUP BY g.gameid
 ORDER BY gameid DESC;

2 个答案:

答案 0 :(得分:1)

更新

得到了Duder!

小提琴: http://sqlfiddle.com/#!9/af1f2b/18

SELECT
    teamid,
    avg(total),
    sub_table.lastgame,   
    sub_table.gamedate   
FROM
    (SELECT
            teamid,
            gameid as lastgame,
            total,
            gamedate,
            @rn:=CASE
                WHEN @var_teamid = teamid THEN @rn + 1
                ELSE 1
            END AS rn,
            @var_teamid:=teamid
    FROM
        (SELECT @var_teamid:=NULL, @rn:=NULL) vars, games

    ORDER BY teamid , gamedate DESC
    ) as sub_table WHERE
        rn <= 2 group by teamid order by teamid, gamedate desc

答案 1 :(得分:0)

@Potorious Pet0让我朝着正确的方向前进,经过几次摔跤之后,我得到了(相当丑陋的)答案。 The results显示我正在寻找的内容。这是我提出的SQL:

SELECT gid, tid, gdate, AVG(total)
  FROM (
        SELECT @r := IF(@c = Concat(gid, tid), @r + 1, 1) AS rownum, 
               @c := Concat(gid, tid), 
               prevgames.* 
          FROM (SELECT @c := NULL, @r := 0) AS _init 
          JOIN (
                SELECT gkey.gameid AS gid, 
                       gkey.teamid AS tid, 
                       gkey.gamedate AS gdate, 
                       gprev.* 
                  FROM games AS gkey 
                  LEFT OUTER JOIN games AS gprev 
                    ON (gkey.teamid = gprev.teamid AND gkey.gameid > gprev.gameid) 
                 ORDER BY gid, tid, gamedate DESC) AS prevgames
        ) AS g
WHERE rownum <= 2
GROUP BY gid, tid, gdate;