2013-02-14 11 views
5

Mam funkcję agregującą, która wykonuje grupę według (kol. A). Wybiera maksymalną wartość z zestawu kolumn (col B), ale chcę również zwrócić inną wartość z kolumny w tym samym wierszu (col C). Ale jeśli grupuje 3 wiersze, wybiera pierwszą wartość z kolumny C, a nie kolumnę z maksymalną (MAX (col B)).SQL Uzyskaj inne wiersze z funkcji agregacji

A B C 
1  75 jkl 
1 100 abc 
1 125 dae 
2 200 def 
3 300 ghi 

"SELECT A, MAX(B), C FROM myTable where B > 50 GROUP BY A" 

returns (first row) A => 1, B => 125, C => jkl 

I want it to return 

A => 1, B => 125, C => dae 

Odpowiedz

9

Będziemy chcieli użyć podzapytania, że ​​dostanie się max(b) przez każdego A a następnie dołączyć tę wartość z powrotem do stolika do zwrotu pozostałych kolumn, które odpowiadają wartości podkwerendzie:

select * 
from mytable t1 
inner join 
(
    select A, max(b) B 
    from mytable 
    where b >50 
    group by a 
) t2 
    on t1.a = t2.a 
    and t1.b = t2.b 
where t1.b >50 

Zobacz SQL Fiddle with Demo

+0

są zagnieżdżone zapytania SQL szybciej niż powiedzmy, po prostu zbieranie MAX (B), a następnie uruchamianie pojedynczego zapytania dla każdego z MAX (B)? –

+0

@ TheHawk Nie rozumiem o co pytasz, czy możesz wyjaśnić? – Taryn

+0

jeśli uruchomię zagnieżdżone zapytanie samodzielnie, otrzymam zestaw wyników ze wszystkimi max (b). Przeszukuję zestaw wyników max (b) i wykonuję selekcje dla każdego max (b). Zasadniczo to samo, co zapytanie zagnieżdżone, ale rodzaj robienia tego ręcznie –

5

ponieważ nie wspominając o RDBMS używasz, należy użyć tej kwerendy, która działa na prawie wszystkich RDBMS

SELECT a.* 
FROM tableName a 
     INNER JOIN 
     (
      SELECT A, MAX(b) max_B 
      FROM tableName 
      WHERE b > 50 
      GROUP BY A 
     ) b ON a.A = b.A AND 
      a.B = b.max_B 

Ale jeśli twoje okno pomocy RDBMS działa, możesz użyć DENSE_RANK()

SELECT A, B, C 
FROM  
     (
      SELECT A, B, C, 
        DENSE_RANK() OVER (PARTITION A ORDER BY B DESC) rn 
      FROM tableName 
      WHERE b > 50 
      GROUP BY  
     ) a 
WHERE rn = 1 

+0

są zagnieżdżonymi zapytaniami SQL szybszymi niż po prostu zbieranie MAX (B), a następnie uruchamianie pojedynczego zapytania dla każdego z MAX (B)? –

+0

Będzie bardziej wydajne, jeśli dodasz indeks złożony w kolumnie A i B. –

+0

Dzięki za notatkę DENSE_RANK. Czy to samo pytanie, ale dla SQL Server – Scott

3

jest to bardzo powszechny problem - "pokaż mi inne kolumny w wierszach odpowiadających moim kryteriom agregacji min()/max()." W przypadku dużych tabel strategie podzapytania mogą stać się bardzo powolne, a funkcje rankingu czasami nie są dużo lepsze.

Jeśli jesteś gotów, aby uzyskać głowy wokół niego, jest to zdecydowanie najbardziej wydajnych sposobów, aby sobie z tym poradzić (choć znowu nie najbardziej czytelny):

SELECT A, cast(left(val, 8) as int) AS B, substring(val, 9, 999) AS C 
FROM (SELECT A, max(str(B, 8) + C) AS val FROM myTable GROUP BY A) t 

można złączyć co chcesz do tego, co masz max, a następnie rozpakuj je w zapytaniu zewnętrznym. Voilá.

Zwróć uwagę, że spowoduje to uzyskanie innych wyników niż rozwiązania opublikowane przez bluefeet i JW, ponieważ jeśli istnieje wiele pasujących wartości maksymalnych na grupę, ta metoda wybierze zwycięzcę (największego C), podczas gdy inni zwrócą wiele rekordów . Tak więc, jeśli wartość 3. B wynosi 100 zamiast 125, to zwróci 1, 100, dae, podczas gdy inne rozwiązania zwrócą zarówno 1, 100, abd i 1, 100, dae.

+0

To wygląda świetnie. Jednak C jest brane pod uwagę przy uruchamianiu funkcji MAX. Ma również MAXing over C, ale uważam, że chce, aby wartość C była równa "MAXimum B dla konkretnego A". Oznacza to, że zapytanie musi mieć dwa wyniki. To dlatego, że nie powinniśmy brać pod uwagę wartości C. – VISQL