2013-05-13 11 views
5

Nicht sicher, wie diese Frage formuliert wird, aber ich möchte eine Aggregatabfrage auf mehrere Zeilen angewendet. Hoffentlich sollte ein Beispiel dies erleichtern. Angenommen, ich habe folgende Daten:Kombinierte aggregierte und nicht aggregierte Abfrage 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 

Und für jeden Spieler in jedem Jahr, ich will ihre „Karriere Jahr“ berechnen, dh die Anzahl der Jahre, die sie gespielt haben:

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 

es wäre natürlich, diese Transformation als SELECT player, year, games, year - min(year) + 1 as cyear FROM baseball GROUP by player zum Ausdruck bringen, sondern wegen der Regeln für die aggregierte Abfragen der Ausdruck nur einmal für jede Gruppe ausgewertet wird:

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

wie kann ich diese überwinden Problem im Allgemeinen (d. h. nicht nur für diesen Fall, sondern immer dann, wenn ich eine arithmetische Operation durchführen möchte, die eine vorhandene Spalte und eine einzelne pro-Gruppe-Zahl kombiniert mit einer Aggregatfunktion kombiniert)?

+1

Bitte geben Sie das RDBMS, die Sie, indem Sie die entsprechenden Tag (Oracle, SQL Server, MySQL, etc.) zielen kann es Antworten, die den Vorteil der Sprache oder Produkt nehmen Funktionen, die nicht universell unterstützt werden Durch das Tagging mit einem bestimmten RDBMS erhält Ihre Frage möglicherweise die Aufmerksamkeit von Personen, die besser dafür geeignet sind, sie zu beantworten – Taryn

+1

@blue Füße Ich interessiere mich für Antworten, die allgemein gelten, nicht für ein bestimmtes RDBMS. – hadley

Antwort

4

Sie können ROW_NUMBER für die Karriere-Jahr verwenden:

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

Werfen Sie einen Blick auf die mächtige OVER clause.

+0

Danke - das hilft für diesen speziellen Fall, aber nicht im Allgemeinen (zB 'Spiele/max (Spiele)' – hadley

+0

@hadley: Dann verwende 'Spiele/MAX (Spiele) OVER ...', bearbeitete meine Antwort. –

+0

Das ist nützlich - Es wird nicht von dem RDMS unterstützt, den ich für das Prototyping verwende (sqlite), aber ich sehe, dass postgresql es auch unterstützt – hadley

0

Verwenden Sie einfach mehrere Gruppe von ... und die Summe auf das gewünschte Feld

GROUP BY player, year 
3

Eine einfache Methode ist jedes Spielers Startjahr als Aggregat Abfrage zu berechnen, und die Daten mit dem Original kommen. Diese Art von „Sequenz basiert“ Abfragen sind in der Regel heikel einen Satz basierte Sprache ausdrücken in :(

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

Wenn Sie noch nicht oder mehr beträgt, dann ... eine echte Datenbank erhalten. dass Failing, Sie können es mit einer Unterabfrage tun.

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 
Verwandte Themen