【问题标题】:Selecting a Record With MAX Value选择具有 MAX 值的记录
【发布时间】: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 吗?如果出现平局,您似乎正在寻找一个随机的。

标签: tsql aggregate-functions


【解决方案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 
      )
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-10-06
        • 2014-10-19
        • 2021-03-22
        • 2012-05-18
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多