5

Not sure how to phrase this question, but I want an aggregate query applied to multiple rows. Hopefully an example should make this easier. Assuming I have the following data:

  player  | year | games
-------------------------
ausmubr01 | 2006 | 139
ausmubr01 | 2007 | 117
bondsba01 | 2006 | 130
bondsba01 | 2007 | 126
stairma01 | 2006 | 26
stairma01 | 2006 | 77
stairma01 | 2006 | 14
stairma01 | 2007 | 125

And for each player in each year, I want to calculate their "career year", i.e. the number of years they've been playing:

  player  | year | games | cyear
 --------------------------------
ausmubr01 | 2006 | 139   |  1
ausmubr01 | 2007 | 117   |  2
bondsba01 | 2006 | 130   |  1
bondsba01 | 2007 | 126   |  2
stairma01 | 2006 | 26    |  1
stairma01 | 2006 | 77    |  2
stairma01 | 2006 | 14    |  3
stairma01 | 2007 | 125   |  4

It would be natural to express this transformation as SELECT player, year, games, year - min(year) + 1 as cyear FROM baseball GROUP by player but because of the rules for aggregate queries the expression is only evaluated once for each group:

  player  | year | games | cyear
 --------------------------------
ausmubr01 | 2006 | 139   |  1
bondsba01 | 2006 | 130   |  1
stairma01 | 2006 | 26    |  1

How can I overcome this problem in general (i.e. not just for this case but whenever I want to perform an arithmetic operation combining an existing column and a single per-group number computed with an aggregate function)?

4

4 回答 4

4

您可以 ROW_NUMBER在职业年使用:

SELECT player, year, games,
       cyear = ROW_NUMBER () OVER (PARTITION BY player ORDER BY year),
       gamesPerMax = 1.0 * games / MAX(games) OVER (PARTITION BY player)
FROM dbo.TableName

演示

看看强大的OVER条款

于 2013-05-13T21:39:41.550 回答
3

一种直接的方法是将每个玩家的起始年份计算为聚合查询,并将数据与原始数据连接起来。这些“基于序列”的查询通常很难用基于集合的语言表达:(

WITH tmp as (
  select player, min(year) as minyear 
  from table 
  group by player
);

select t.*, t.year - t.minyear + 1 as cyear
from table as t, tmp
where t.player = tmp.player;
于 2013-05-13T21:46:47.220 回答
1

如果你没有 WITH 或 OVER,那么……获取一个真正的数据库。如果做不到这一点,您可以使用子查询来做到这一点:

SELECT t.*, t.year - subtable.minyear + 1 AS cyear
FROM table AS t
JOIN (
  select player, min(year) as minyear 
  from table 
  group by player
) AS SubTable
ON T.player = SubTable.player
于 2013-05-14T00:52:00.600 回答
0

只需使用多个 group by... 并在所需字段上求和

GROUP BY player, year
于 2013-05-13T21:44:20.987 回答