如何检索SQL中其他列中与max对应的值?

时间:2012-11-13 20:03:21

标签: 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服务器能够理解我需要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. 使用其他独立请求的结果进行加入,该请求将返回所有项目/最大(日期)夫妇
  2. 在where子句中使用子请求结果,每个项目的值都不同。
  3. 任何人都可以提供一个理由(或指向一个理由的指针)来优先选择其中一个吗?

5 个答案:

答案 0 :(得分:4)

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 version

为了响应您的编辑,确定哪种方法将更好地执行的唯一方法是评估每个查询的执行计划。决定最快方法的因素有很多,当然DBMS本身就是其中一个因素。无论采用何种方法,良好的查询引擎都应该能够推导出相同或类似的执行计划。也就是说,使用派生表(即方法#1)可能对查询引擎更加明确(即使对查询的读者不太明确),因此可能表现得更好。通常情况下,派生表的性能优于相关子查询(我的解决方案和方法#2)。但是,在我有证据支持这一改变之前,我不会改变方法。同样,了解哪些会更好地执行某些操作的唯一方法是根据您的数据评估执行计划。

答案 1 :(得分:3)

如果您使用的是几乎所有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>)

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

答案 2 :(得分:2)

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

答案 3 :(得分:1)

试试这个:

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

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

答案 4 :(得分:-1)

这是您可能需要的代码:

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",该表格指的是相同项目最大值的记录