2013-05-13 10 views
5

Non so come formulare questa domanda, ma voglio una query aggregata applicata a più righe. Speriamo che un esempio dovrebbe renderlo più facile. Supponendo che ho i seguenti dati:Query aggregata e non aggregata combinata in SQL

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 

E per ogni giocatore di ogni anno, voglio calcolare il loro "anni di carriera", vale a dire il numero di anni che hanno giocato:

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 

sarebbe naturale per esprimere questa trasformazione come SELECT player, year, games, year - min(year) + 1 as cyear FROM baseball GROUP by player, ma a causa delle regole per le query di aggregazione l'espressione viene valutata solo una volta per ogni gruppo:

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

come posso superare questo problema in generale (es. non solo per questo caso ma ogni volta che voglio eseguire un'operazione aritmetica combinando una colonna esistente e un singolo numero per gruppo calcolato con una funzione aggregata)?

+1

si prega di specificare l'RDBMS che si prendono di mira aggiungendo il tag appropriato (Oracle, SQL Server, MySQL, ecc) ci possono essere risposte che sfruttano la lingua o del prodotto funzionalità che non sono universalmente supportate. Inoltre, taggandole con un RDBMS specifico, la tua domanda potrebbe ricevere l'attenzione delle persone più adatte a rispondergli – Taryn

+1

@blue piedi Sono interessato a risposte che si applicano in generale, non a un RDBMS specifico. – hadley

risposta

4

È possibile utilizzare ROW_NUMBER alla carriera anni:

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 

Demo

Dai un'occhiata alla potente OVER clause.

+0

Grazie - questo ti aiuta in questo caso specifico, ma non in generale (ad esempio 'games/max (games)' – hadley

+0

@hadley: Quindi usa 'games/MAX (games) OVER ...', ha modificato la mia risposta –

+0

Questo è utile - Non è supportato dal RDMS che sto usando per la prototipazione (sqlite) ma vedo anche che postgresql lo supporta – hadley

0

Basta usare gruppo multiplo da ... e sum sul campo desiderato

GROUP BY player, year 
3

Un metodo semplice è quello di calcolare l'anno di partenza di ogni giocatore come una query di aggregazione, e unire i dati con l'originale. Questi tipi di "sequenza a base di" query sono di solito difficile da esprimere in un linguaggio basato set :(

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

Se non avete con o più, quindi ... ottenere una vera e propria banca dati. In mancanza di questo, si può fare con una subquery:.

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 
Problemi correlati