选择具有 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 奇怪 - 我想知道为什么这么多年前就接受了这个答案。HAVING
或 WHERE
中应该有一个子查询。
原始答案对哪个版本的 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 值的记录的主要内容,如果未能解决你的问题,请参考以下文章