2017-02-16 3 views
1

У меня есть таблица, которая выглядит следующим образом:SQL Select столбец с максимальным значением в другом столбце

Name Group Value 
A  1  0 
B  1  2 
C  1  5 
D  2  6 
E  2  0 
F  3  3 

Я хочу, чтобы выбрать имя с максимальным значением в каждой группе. Например, есть 3 группы, так что результат будет:

Name 
C  (because it has the maximum value (5) within group 1) 
D  (because it has the maximum value (6) within group 2) 
F  (because it has the maximum value (3) within group 3) 

Я пытался писать что-то вроде этого:

SELECT name FROM table 
WHERE value = (SELECT max(value) FROM table) 
GROUP BY group 

Но макс (значение) возвращает глобальное максимальное значение всей таблицы ((6) в этом примере). Как это исправить?

+1

MySQL или SQL-сервер? –

+0

Я удалил несовместимые теги базы данных –

+0

Если это не MySQL или Access, посмотрите 'RANK' – dnoeth

ответ

2

Есть много способов сделать это, вот некоторые из них:

rextester для всех из них: http://rextester.com/DTWB67044

max()over() версия:

with cte as (
    select *, MaxValue = max([Value]) over (partition by [Group]) 
    from t 
) 
select Name 
from cte 
where [Value] = MaxValue; 

inner join версия:

select t.Name 
from t 
    inner join (
    select MaxValue=max(value), [Group] 
    from t 
    group by [Group] 
    ) as m 
     on t.[Group] = m.[Group] 
    and t.[Value] = m.MaxValue; 

cross apply() версия:

select t.Name 
from t 
    cross apply (
    select top 1 
     [Value] 
     from t as i 
     where i.[Group] = t.[Group] 
     order by i.[Value] desc 
    ) as x 
    where t.[Value] = x.[Value]; 

Если вы будете возвращаться только одно значение для каждой группы, они работают, а также:

common table expression с row_number() версия:

with cte as (
select *, rn = row_number() over (partition by [Group] order by [Value] desc) 
from t 
) 
select Name 
from cte 
where rn = 1; 

top with ties версия:

select top 1 with ties 
    t.Name 
from t 
order by row_number() over (partition by [Group] order by [Value] desc); 
+0

Это замечательно. Какой из них самый быстрый/лучший для большого набора данных? – user3685285

+0

Вы возвращаете все строки с максимальным значением для каждой группы или только одну строку с максимальным значением для каждой группы? В общем, я бы порекомендовал первый из каждого установленного выше. – SqlZim

+0

Это точно так же, как в примере вашего рекстера. Просто имена для всех строк с максимальным значением в каждой группе. Благодаря! – user3685285

2

Вы вроде как близко. Вы должны коррелировать подзапрос вместо агрегацию внешнего запроса:

SELECT t.* 
FROM table t 
WHERE value = (SELECT max(t2.value) FROM table t2 WHERE t2.group = t.group); 

Это стандартный SQL и будет работать в любой базе данных. Вы можете просто выбрать name, если это все, что вам нужно, но я считаю, что group также будет полезен.

В большинстве баз данных для этой цели вы бы использовали row_number().

В SQL Server, это было бы более характерно сделать:

select t.* 
from (select t.*, 
      row_number() over (partition by group order by value desc) as seqnum 
     from t 
    ) t 
where seqnum = 1; 

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

+0

Есть ли дополнительная скобка в примере SQL Server? Я не могу заставить его работать. – user3685285

+0

@ user3685285 отсутствует перед 'partition' – SqlZim

0

Это даст вам желаемый результат.

Select name, max(value) from table group by group order by group 

Выход:

C | 5 
D | 6 
F | 3 
+0

Было бы неплохо, если бы все было так просто, но это не работает или имеет смысл для меня. Может ли кто-нибудь подтвердить или аннулировать этот ответ? – user3685285

+0

Вы можете проверить его, выполнив. Но я уверен в моем подходе. Я даже выполнил его. – leo

+0

Я бы хотел, чтобы ваш ответ был правильным, но запрос даже не работает для меня. Это MS SQL Server. Если два человека говорят, что это сработает для них, тогда, может быть, я еще раз взгляду, но пока это не имеет смысла для меня. – user3685285

Смежные вопросы