2013-07-01 9 views
13

Ich versuche, den maximalen Wert aus einer Spalte auszuwählen, während die Gruppierung durch eine andere nicht eindeutige ID-Spalte, die mehrere doppelte Werte hat. Die ursprüngliche Datenbank sieht ungefähr so ​​aus:Wählen Sie mehrere Spalten (keine Aggregatfunktion) mit GROUP BY

mukey | comppct_r | name | type 
65789 | 20  | a | 7n 
65789 | 15  | b | 8m 
65789 | 1   | c | 1o 
65790 | 10  | a | 7n 
65790 | 26  | b | 8m 
65790 | 5   | c | 1o 
... 

Diese Verwendung funktioniert gut:

SELECT c.mukey, Max(c.comppct_r) AS ComponentPercent 
FROM c 
GROUP BY c.mukey; 

, die eine Tabelle zurückgibt, wie:

mukey | ComponentPercent 
65789 | 20 
65790 | 26 
65791 | 50 
65792 | 90 

ich andere Spalten hinzufügen zu können, wollen in ohne die GROUP BY-Funktion zu beeinflussen, um Spalten wie Name und Typ in die Ausgabetabelle einzubeziehen:

mukey | comppct_r | name | type 
65789 | 20  | a | 7n 
65790 | 26  | b | 8m 
65791 | 50  | c | 7n 
65792 | 90  | d | 7n 

aber es gibt immer einen Fehler aus, der besagt, dass ich eine Aggregatfunktion mit Select-Anweisung verwenden muss. Wie soll ich das machen?

+1

Was ist Ihr erwartetes Ergebnis? –

+0

Hinzugefügt, dass op, Danke – Dylansq

Antwort

17

Sie haben selbst ein Problem. Dies ist eine der möglichen Lösungen:

select c.mukey, c.comppct_r, c.name, c.type 
from c yt 
inner join(
    select c.mukey, max(c.comppct_r) comppct_r 
    from c 
    group by c.mukey 
) ss on c.mukey = ss.mukey and c.comppct_r= ss.comppct_r 

Ein anderer möglicher Ansatz, gleiche Ausgabe:

select c1.* 
from c c1 
left outer join c c2 
on (c1.mukey = c2.mukey and c1.comppct_r < c2.comppct_r) 
where c2.mukey is null; 

Es gibt eine umfassende und erläuternde Antwort zum Thema hier: SQL Select only rows with Max Value on a Column

+0

Was bedeutet die 'ss' in "ss auf c.mukey = ss.mukey und c.comppct_r = ss.comppct_r"? – Dylansq

+1

'ss' ist der Name, den ich der abgeleiteten Tabelle (die zwischen Klammern deklarierte Struktur) gegeben habe –

+0

Wie funktioniert die zweite Lösung? in meinem Fall tut es nichts - zeigt nur alle Zeilen an. Es scheint, dass dieser Ansatz auch die Gruppierung verwenden muss ... –

0

Versuchen Sie, eine virtuelle Tabelle wie folgt verwendet:

SELECT vt.*,c.name FROM(
SELECT c.mukey, Max(c.comppct_r) AS ComponentPercent 
FROM c 
GROUP BY c.muke; 
) as VT, c 
WHERE VT.mukey = c.mukey 
0

Sie können nicht nur weitere Spalten hinzufügen, ohne dass sie auf die GROUP BY oder Anlegen einer Aggregatfunktion hinzugefügt wird. Der Grund dafür ist, dass die Werte einer Spalte innerhalb einer Gruppe unterschiedlich sein können. Zum Beispiel könnten Sie zwei Zeilen:

mukey | comppct_r | name | type 
65789 | 20  | a | 7n 
65789 | 20  | b | 9f 

Wie soll die aggregierte Gruppe für die Spalten aussehen name und type?

Wenn Name und Typ immer die gleiche innerhalb einer Gruppe ist, fügen Sie einfach, um es die GROUP BY Klausel:

SELECT c.mukey, Max(c.comppct_r) AS ComponentPercent 
FROM c 
GROUP BY c.muke, c.name, c.type; 
1

Jede Nicht-Aggregat Spalte sollte in Group By-Klausel sein .. warum ??

    t1 
x1   y1   z1 
1   2    5 
2   2    7 

Jetzt versuchen Sie eine Abfrage wie zu schreiben:

select x1,y1,max(z1) from t1 group by y1; 

Nun ist diese Abfrage nur eine Zeile, führen aber, was der Wert von x1 sein sollte ?? Dies ist im Grunde ein undefiniertes Verhalten. Um dies zu umgehen, wird SQL diese Abfrage fehlschlagen.

Jetzt kommen Sie zum Punkt, Sie können entweder Aggregatfunktion für x1 wählen oder Sie können x1 hinzufügen, um zu gruppieren. Beachten Sie, dass dies von Ihrer Anforderung abhängt.

Wenn Sie alle Zeilen mit Aggregation auf z1-Gruppierung nach y1 möchten, können Sie den SubQ-Ansatz verwenden.

Select x1,y1,(select max(z1) from t1 where tt.y1=y1 group by y1) 
from t1 tt; 

Dies ein Ergebnis wie produzieren:

    t1 
x1   y1   max(z1) 
1   2    7 
2   2    7