ti-enxame.com

Selecionando um registro com valor máximo

No SQL Server 2008, tenho uma tabela CUSTOMERS que possui duas colunas como:

ID, BALANÇO

Como escrever a consulta que seleciona o ID do cliente com saldo máximo " da maneira mais eficaz "?

Opção 1: ORDER BY BALANCE and SELECT TOP(1) -> custa muito.

Opção 2: Primeiramente Get MAX amount, faça outra consulta que use o valor em where clause -> custa muito e não parece confiável.

37
Ahmet Altun

Nota: Uma revisão incorreta desta resposta foi editada. Revise todas as respostas.

Uma subseleção na cláusula WHERE para recuperar o maior BALANCE agregado em todas as linhas. Se vários valores ID compartilharem esse valor de saldo, todos serão retornados.

SELECT 
  ID,
  BALANCE
FROM CUSTOMERS
WHERE BALANCE = (SELECT MAX(BALANCE) FROM CUSTOMERS)
60
Michael Berkowski

Aqui está uma opção se você tiver vários registros para cada Cliente e estiver procurando o saldo mais recente para cada um (digamos que sejam registros datados):

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
10
Gary

Como assim, custa demais? Demais o que?

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

Se sua tabela estiver adequadamente indexada (Saldo) e for necessário haver um índice no PK, não tenho certeza do que você quer dizer com custos demais ou não parece confiável. Não há nada confiável sobre um agregado que você esteja usando e dizendo para ele fazer. Nesse caso, MAX() faz exatamente o que você manda fazer - não há nada de mágico nisso.

Dê uma olhada em MAX() e se você deseja filtrá-lo, use a cláusula HAVING.

7
JonH

Digamos que, para um usuário, haja revisão para cada data. A seguir, será coletado o registro da revisão máxima de cada data para cada funcionário.

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
2
sandip giri

A consulta respondida por sandip giri foi a resposta correta, aqui um exemplo semelhante obtendo o ID máximo (PresupuestoEtapaActividadHistoricoId), após calcular o valor máximo (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 
)
1
Edinson Serrano