2013-02-14 5 views
5

У меня есть сводная функция, которая выполняет группу с помощью (col A). Он выбирает максимальное значение из набора столбцов (col B), но я также хочу вернуть другое значение из столбца в той же строке (col C). Но если он группирует 3 строки, он выбирает первое значение из столбца C, а не столбец с максимальным значением (MAX (col B)).SQL Get Other Rows From Aggregate Function

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 

ответ

9

Вы хотите использовать подзапрос, который будет получить max(b) каждым A, а затем присоединиться это значение обратно к столу, чтобы вернуть оставшиеся столбцы, соответствующие значения подзапроса:

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 

См SQL Fiddle with Demo

+0

были вложенными SQL-запросами быстрее, чем просто собирать MAX (B), а затем запускать один запрос для каждого из MAX (B)? –

+0

@ TheHawk Я не понимаю, что вы просите, можете ли вы уточнить? – Taryn

+0

если я запускаю вложенный запрос сам по себе, я получаю результирующий набор со всеми max (b). Я прокручиваю результирующий набор max (b) и запускаю select для каждого max (b). В принципе то же самое, что и вложенный запрос, но вроде этого вручную –

5

, так как вы не говоря уже о СУБД вы используете, используйте этот запрос, который работает практически на всех 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 

Но если функция поддержки RDBMS поддерживает, вы можете использовать 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

являются вложенными SQL-запросами быстрее, чем просто собирать MAX (B), а затем запускать один запрос для каждого из MAX (B)? –

+0

Это будет более эффективно, если вы добавите составной индекс в столбцы A и B. –

+0

Спасибо за примечание DENSE_RANK. Если бы один и тот же вопрос, но для SQL Server – Scott

3

Это очень распространенная проблема - «Покажите мне другие столбцы в строках, соответствующие моим критериям min()/max()». На больших таблицах стратегии подзапроса могут стать очень медленными, а ранжирующие функции иногда не намного лучше.

Если вы готовы, чтобы получить голову вокруг него, это, безусловно, самый производительный способ справиться с этим (хотя опять же, не самый читаемый):

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 

Вы можете сцепить все, что вы хотите к чему вы находитесь max ing, затем извлеките его во внешнем запросе. Вуаля.

Обратите внимание, что это приведет к различным результатам, чем решения, отправленные bluefeet и JW, в том случае, если для каждой группы указано несколько совпадающих максимальных значений, этот метод будет выбирать победителя (самый большой C), тогда как другие возвратят несколько записей , Таким образом, если значение 3-го В было 100 вместо 125, это вернет 1, 100, dae, тогда как другие решения возвратят оба 1, 100, abd и 1, 100, dae.

+0

Это выглядит великолепно. Однако C учитывается при выполнении функции MAX. Это MAXing над C, но я считаю, что он хочет, чтобы связанное значение C было «MAXimum B для конкретного A». Это означает, что запрос должен иметь два результата. Это связано с тем, что мы не должны учитывать значение С. – VISQL