Выбор записи с максимальным значением - PullRequest
35 голосов
/ 05 декабря 2011

В SQL Server 2008 у меня есть таблица КЛИЕНТОВ , которая имеет два столбца:

ID, БАЛАНС

Как мне написать запрос, который выбирает идентификатор клиента с максимальным балансом, " наиболее эффективным способом "?

Вариант 1: ORDER BY BALANCE and SELECT TOP(1) -> стоит слишком дорого.

Вариант 2: сначала Get MAX amount, затем сделайте другой запрос, который использует сумму в where clause ->, стоит слишком дорого и не кажется надежным.

Ответы [ 5 ]

59 голосов
/ 05 декабря 2011

Примечание : неверный пересмотр этого ответа был удален. Пожалуйста, просмотрите все ответы.

Подвыбор в предложении WHERE для получения наибольшего значения BALANCE, агрегированного по всем строкам. Если несколько значений ID разделяют это значение баланса, будет возвращено все.

SELECT 
  ID,
  BALANCE
FROM CUSTOMERS
WHERE BALANCE = (SELECT MAX(BALANCE) FROM CUSTOMERS)
7 голосов
/ 02 июня 2017

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

SELECT ID, BALANCE FROM (
    SELECT ROW_NUMBER() OVER (PARTITION BY ID ORDER BY DateModified DESC) as RowNum, ID, BALANCE
    FROM CUSTOMERS
) C
WHERE RowNum = 1
7 голосов
/ 05 декабря 2011

Что вы имеете в виду, стоит слишком дорого?Слишком много, что?

SELECT MAX(Balance) AS MaxBalance, CustomerID FROM CUSTOMERS GROUP BY CustomerID

Если ваша таблица правильно проиндексирована (баланс) и должен быть индекс на ПК, то я не уверен, что вы имеете в виду и в отношении затрат.много или кажется ненадежным?Нет ничего ненадежного в том агрегате, который вы используете и который указывает на это.В этом случае MAX() делает именно то, что вам говорят - в этом нет ничего волшебного.

Посмотрите на MAX(), и если вы хотите отфильтровать его, используйте предложение HAVING.

2 голосов
/ 16 июля 2015

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

select job, adate, rev, usr, typ 
from tbl
where exists (  select 1 from ( select usr, adate, max(rev) as max_rev 
                                from tbl
                                group by usr, adate 
                              ) as cond
                where tbl.usr=cond.usr 
                and tbl.adate =cond.adate 
                and tbl.rev =cond.max_rev
             )
order by adate, job, usr
1 голос
/ 21 марта 2017

На запрос , на который ответил sandip giri , был правильный ответ, здесь аналогичный пример получения максимального идентификатора (PresupuestoEtapaActividadHistoricoId) после вычисления максимального значения (Base)

select * 
from (
    select PEAA.PresupuestoEtapaActividadId,
        PEAH.PresupuestoEtapaActividadHistoricoId,             
        sum(PEAA.ValorTotalDesperdicioBase) as Base,
        sum(PEAA.ValorTotalDesperdicioEjecucion) as Ejecucion
    from hgc.PresupuestoActividadAnalisis as PEAA
    inner join hgc.PresupuestoEtapaActividad as PEA
        on PEAA.PresupuestoEtapaActividadId = PEA.PresupuestoEtapaActividadId
    inner join hgc.PresupuestoEtapaActividadHistorico as PEAH
        on PEA.PresupuestoEtapaActividadId = PEAH.PresupuestoEtapaActividadId                                                         
    group by PEAH.PresupuestoEtapaActividadHistoricoId, PEAA.PresupuestoEtapaActividadId    
) as t
where exists (
    select 1 
    from (
        select MAX(PEAH.PresupuestoEtapaActividadHistoricoId) as PresupuestoEtapaActividadHistoricoId                                                                     
        from hgc.PresupuestoEtapaActividadHistorico as PEAH                       
        group by PEAH.PresupuestoEtapaActividadId  
    ) as ti
    where t.PresupuestoEtapaActividadHistoricoId = ti.PresupuestoEtapaActividadHistoricoId 
)
...