繁体   English   中英

如何在SQL的另一列中检索与最大值对应的值?

[英]How to retrieve the value which corresponding to the max in an other column in SQL?

我有下表,它表示项目的评估。

ITEM             REFERENCEDATE     VALUATION
------------------------------------------------
A                25/01/2012        25.35
A                26/01/2012        51.35
B                25/01/2012        25.00

编辑:(ITEM,REFERENCEDATE)是唯一索引。

目标是获得一组物料的最新估值。 这意味着我正在尝试创建一个将返回类似内容的SQL请求

ITEM             REFERENCEDATE     VALUATION
------------------------------------------------
A                26/01/2012        51.35
B                25/01/2012        25.00

在进行有关GROUP BY的教程时,我最终尝试

SELECT A.ITEM, A.VALUATION, MAX(A.REFERENCEDATE)
FROM VALUATIONS A
GROUP BY A.ITEM

充满希望的是,SQL Server将理解我需要该行的A.VALUATION,以实现当前结果行上表示的ITEM的A.REFERENCEDATE的最大值。

但是,相反,我有此令人不愉快的错误消息:

Column 'VALUATIONS.VALUATION' is invalid in the select list because it is not contained 
in either an aggregate function or the GROUP BY clause.

如何指示应该使用达到REFERENCEDATE最大值的VALUATION?

注意:我需要至少在Oracle和SQL Server上有效的解决方案

编辑:谢谢大家的帮助。 我被困在一个漏洞中,试图只使用一个SELECT ... GROUP BY请求。 现在,我发现有两种方法可以围绕相同的想法进行阐述:

  1. 用另一个独立请求的结果进行JOIN,它将返回所有item / max(date)对
  2. 在where子句中使用子请求结果将为每个项目具有不同的值。

任何人都可以提供一个理由(或一个理由的指针)来优先于另一个吗?

Select V.Item, V.ReferenceDate, V.Valuation
From Valuations As V
Where V.ReferenceDate = (
                        Select Max(V1.ReferenceDate)
                        From Valuations As V1
                        Where V1.Item = V.Item
                        )

SQL Fiddle版本

响应您的编辑,唯一确定哪种方法效果更好的唯一方法是评估每个查询的执行计划。 确定最快的方法有很多因素,DBMS本身就是其中之一。 一个好的查询引擎应该能够推断出相同或相似的执行计划,而不管采用哪种方法。 也就是说,使用派生表(即方法#1)对查询引擎可能会更明确(即使对查询的读取者而言不太明确),因此可能会表现更好。 通常情况下,派生表的性能要优于相关子查询(我的解决方案和您的方法2)。 但是,在我有证据支持该更改之前,我不会更改方法。 同样,知道哪种方法在某些方面会更好的唯一方法是根据数据评估执行计划。

如果您正在使用MySQL以外的几乎所有数据库,那么答案是使用排名函数。 特别是row_number您的需求:

select ITEM, REFERENCEDATE, VALUATION
from (select t.*
             row_number() over (partition by item order by referencedate desc) as seqnum
      from t
     ) t
where seqnum = 1 and
      item in (<your list of items>)

行号为每个项目的记录分配一个序列数字。 它从最大参考日期的1开始,然后从下一个最大参考日期的2开始,依此类推(基于order by子句)。 您需要第一个,其中seqnum = 1。

select a.item, a.valuation, a.referencedate
from valuations a
  join (select a2.item, max(referencedate) as max_date
        from valuations a2
        group by a2.item
  ) b ON a.item = b.item and a.referencedate = b.max_date

尝试这个:

SELECT A.ITEM, MAX(A.VALUATION), A.REFERENCEDATE
FROM VALUATIONS A
JOIN 
(
    SELECT A.ITEM, MAX(A.REFERENCEDATE) AS REFERENCEDATE
    FROM VALUATIONS A
    GROUP BY A.ITEM
) B ON A.ITEM = B.ITEM AND A.REFERENCEDATE = B.REFERENCEDATE
GROUP BY A.ITEM, A.REFERENCEDATE

它将从保存max(REFERENCEDATE)的列中选择MAX值。 如果仅希望一列具有最大值,则只需从它可以选择的那一列中进行选择。

这是您可能需要的代码:

Select  *
    From    ItemValues      As  A
    Inner   Join
        ItemValues      As  MaxValuedItem
    On  MaxValuedItem.Id    =   (
        Select  Top 1
            B.Id
            From    ItemValues  As  B
            Where   B.Item_Id   =   A.Item_Id
            Order   By      B.Valuation Desc
    )

您需要对表本身使用"join" ,以引用具有相同项目 最大值的记录。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM