2013-07-01 14 views
13

Próbuję wybrać maksymalną wartość z jednej kolumny, podczas grupowania przez inną nieunikalną kolumnę id, która ma wiele zduplikowanych wartości. Oryginalna baza danych wygląda mniej więcej tak:Wybierz wiele kolumn (funkcja nie agregująca) za pomocą 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 
... 

Działa to dobrze przy użyciu:

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

która zwraca tablicę jak:

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

Chcę, aby móc dodać inne kolumny bez wpływu na funkcję GROUP BY, aby kolumny takie jak nazwa i typ zawierały w tabeli wyjściowej, takie jak:

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

ale zawsze wyświetla komunikat o błędzie z informacją, że muszę użyć funkcji agregującej z instrukcją select. Jak mam to zrobić?

+1

Jaka jest twoja oczekiwany wynik? –

+0

Dodałem to do op, Dzięki – Dylansq

Odpowiedz

17

Trzeba sobie problem. Jest to jedno z możliwych rozwiązań:

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 

Innym możliwym podejściem, samo wyjście:

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; 

Jest wszechstronny i wyjaśniająca odpowiedzi na ten temat tutaj: SQL Select only rows with Max Value on a Column

+0

Co oznacza "ss" w "ss na c.mukey = ss.mukey i c.comppct_r = ss.comppct_r"? – Dylansq

+1

"ss" to nazwa nadana wyprowadzonej tabeli (struktura zadeklarowana między nawiasami) –

+0

jak działa drugie rozwiązanie? w moim przypadku nie robi nic - wyświetla tylko wszystkie wiersze. Wygląda na to, że to podejście musi również wykorzystywać grupę ... –

0

Spróbuj użyć następująco tabelę wirtualny:

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

Nie można po prostu dodać dodatkowe kolumny bez dodawania ich do GROUP BY lub stosując funkcję zbiorczą. Powodem tego jest to, że wartości kolumny mogą być różne w obrębie jednej grupy. Na przykład można mieć dwa rzędy:

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

Jak powinna wyglądać jak grupa zagregowane dla kolumn name i type?

Jeśli nazwa i typ jest zawsze taka sama wewnątrz grupy, wystarczy dodać go do klauzuli GROUP BY:

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

Każda kolumna non-kruszywo powinien być tam w klauzuli Group By .. dlaczego?

    t1 
x1   y1   z1 
1   2    5 
2   2    7 

Teraz próbujesz napisać zapytanie jak:

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

Teraz ta kwerenda spowoduje tylko jeden wiersz, ale jaka powinna być wartość x1 ?? Jest to w zasadzie niezdefiniowane zachowanie. Aby temu zaradzić, SQL spowoduje błąd w tym zapytaniu.

Teraz, dochodząc do sedna, możesz wybrać funkcję agregującą dla x1 lub dodać x1 do grupy przez. Zauważ, że to wszystko zależy od Twoich wymagań.

Jeśli chcesz, aby wszystkie wiersze z agregacją w grupie z1 były wykonywane przez y1, możesz użyć metody SubQ.

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

To będzie produkować wynik takiego:

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