选择具有 MAX 值的记录

Posted

技术标签:

【中文标题】选择具有 MAX 值的记录【英文标题】:Selecting a Record With MAX Value 【发布时间】:2012-01-13 07:51:42 【问题描述】:

在 SQL Server 2008 中,我有一个表 CUSTOMERS 有两列:

身份证, 余额

如何编写查询“以最有效的方式”选择余额最大的客户的 ID?

选项 1:ORDER BY BALANCE and SELECT TOP(1) --> 成本太高。

选项2:首先Get MAX amount,然后使用where clause中的金额进行另一个查询-->成本太高而且似乎不可靠。

【问题讨论】:

如果向 Balance 添加非聚集索引,您应该会发现选项 1 更快。 如果出现平局,您想知道所有的 ID 吗?如果出现平局,您似乎正在寻找一个随机的。 【参考方案1】:

注意:此答案的错误修订已被删除。请查看所有答案。

WHERE 子句中的子选择,用于检索所有行中聚合的最大 BALANCE。如果多个 ID 值共享该余额值,则将全部返回。

SELECT 
  ID,
  BALANCE
FROM CUSTOMERS
WHERE BALANCE = (SELECT MAX(BALANCE) FROM CUSTOMERS)

【讨论】:

我不是 SQL 专家,但 Group By 没有自己的成本吗?? @Baz1nga - 如果没有 group by 子句,您将无法处理具有附加列的聚合函数。一切都有代价,但真正的问题是什么? HAVING 子句中的 BALANCE 列无效,因为它既不包含在聚合函数中,也不包含在 GROUP BY 子句中。 @SergeProfafilecebook 奇怪 - 我想知道为什么这么多年前就接受了这个答案。 HAVINGWHERE 中应该有一个子查询。 原始答案对哪个版本的 SQL Server 有效?它甚至没有任何意义,更不用说实际运行了。 (如果您按 id 汇总,显示的余额是多少?)【参考方案2】:

如果您有每个客户的多条记录,并且正在为每个客户寻找最新的余额(比如它们是过时的记录),这里有一个选项:

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

【讨论】:

这个语法很好,但我注意到SELECT ROW_NUMBER() OVER (PARTITION BY ID ORDER BY DateModified DESC) 的性能在选择更大的数据集时确实会受到影响【参考方案3】:

你的意思是花费太多?太多了怎么办?

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

如果您的表已正确索引(平衡)并且必须在 PK 上有一个索引,那么我不确定您所说的成本过高或看起来不可靠是什么意思?您正在使用并告诉它执行的聚合没有什么不可靠的。在这种情况下,MAX() 完全按照您的要求执行 - 它没有什么神奇之处。

查看MAX(),如果您想过滤它,请使用HAVING 子句。

【讨论】:

【参考方案4】:

假设,对于用户,每个日期都有修订。以下将记录每个员工每个日期的最大修订。

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

【讨论】:

【参考方案5】:

查询answered by sandip giri是正确答案,这里是一个类似的例子,在计算最大值(Base)后得到最大id(PresupuestoEtapaActividadHistoricoId)

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 
)

【讨论】:

以上是关于选择具有 MAX 值的记录的主要内容,如果未能解决你的问题,请参考以下文章

为啥不能为具有 date=max(date) 的最大日期的每个代码选择记录?

选择具有 MAX(Date) 但没有得到明显回报的记录

从具有重复列值的集合中选择第一条记录 C#

使用 Eloquent 选择具有值的最后一条记录

SQL查询以选择在同一列中具有不同值的子记录的父级

LINQ - 选择每组具有最大属性值的记录