web-dev-qa-db-fra.com

Sélection d'un enregistrement avec une valeur MAX

Dans SQL Server 2008, j'ai une table CLIENTS qui a deux colonnes comme:

ID, BALANCE

Comment puis-je écrire la requête qui sélectionne l'ID du client qui a le solde maximum, " de la manière la plus efficace "?

Option 1: ORDER BY BALANCE and SELECT TOP(1) -> coûte trop cher.

Option 2: premièrement Get MAX amount, puis effectuez une autre requête utilisant le montant indiqué dans where clause -> coûte trop cher et ne semble pas fiable.

37
Ahmet Altun

Note: Une révision incorrecte de cette réponse a été supprimée. S'il vous plaît examiner toutes les réponses.

Une sous-sélection dans la clause WHERE pour récupérer le plus grand nombre BALANCE agrégé sur toutes les lignes. Si plusieurs valeurs ID partagent la même valeur, elles seront toutes renvoyées.

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

Voici une option si vous avez plusieurs enregistrements pour chaque client et recherchez le dernier solde pour chacun (disons qu'il s'agit d'enregistrements datés):

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

Que voulez-vous dire coûte trop cher? Trop quoi?

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

Si votre table est correctement indexée (balance) et qu'il doit y avoir un index sur le PK, je ne suis pas sûr de ce que vous voulez dire par coûts trop élevés ou semble peu fiable? Il n’ya rien de douteux dans l’agrégat que vous utilisez et que vous lui dites de faire. Dans ce cas, MAX() fait exactement ce que vous lui demandez de faire - il n'y a rien de magique à ce sujet.

Jetez un coup d'œil à MAX() et si vous souhaitez le filtrer, utilisez la clause HAVING.

7
JonH

Dites, pour un utilisateur, il y a une révision pour chaque date. Ce qui suit ramassera l'enregistrement pour la révision maximale de chaque date pour chaque employé.

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

La requête répondu par sandip giri était la bonne réponse, voici un exemple similaire qui obtient l'identifiant maximal (PresupuestoEtapaActividadHistoricoId), après avoir calculé la valeur maximale (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