简体   繁体   English

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

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

I have the following table, which represents valuations of items. 我有下表,它表示项目的评估。

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

Edit: (ITEM, REFERENCEDATE) is a unique index. 编辑:(ITEM,REFERENCEDATE)是唯一索引。

The goal is to get the latest valuations for a set of item. 目标是获得一组物料的最新估值。 Which means i'm trying to create a SQL request that would return something like 这意味着我正在尝试创建一个将返回类似内容的SQL请求

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

Flowing a tutorial on GROUP BY, I ended up trying 在进行有关GROUP BY的教程时,我最终尝试

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

Full of hope that the SQL server would understand that I need A.VALUATION for the line which realizes the max for A.REFERENCEDATE for the ITEM represented on the current result line. 充满希望的是,SQL Server将理解我需要该行的A.VALUATION,以实现当前结果行上表示的ITEM的A.REFERENCEDATE的最大值。

But instead, I have this unpleasant error message: 但是,相反,我有此令人不愉快的错误消息:

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

How can I indicate that the VALUATION where the maximum of REFERENCEDATE is reached should be used ? 如何指示应该使用达到REFERENCEDATE最大值的VALUATION?

Note: I need a solution that works at least on Oracle and SQL Server 注意:我需要至少在Oracle和SQL Server上有效的解决方案

EDIT: Thanks everybody for your help. 编辑:谢谢大家的帮助。 I was stuck in a hole try to get away with only one single SELECT ... GROUP BY request. 我被困在一个漏洞中,试图只使用一个SELECT ... GROUP BY请求。 Now I see there are two approaches that articulate around the same idea: 现在,我发现有两种方法可以围绕相同的想法进行阐述:

  1. Making a JOIN with the result of an other independant request that will return all the item/max(date) couples 用另一个独立请求的结果进行JOIN,它将返回所有item / max(date)对
  2. Using a subrequest result in the where clause which will have a different value for each item. 在where子句中使用子请求结果将为每个项目具有不同的值。

Could anybody provide a reason (or a pointer to a reason) to prefer one to the other ? 任何人都可以提供一个理由(或一个理由的指针)来优先于另一个吗?

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 SQL Fiddle版本

In response to your edit, the only way to know for sure which approach will perform better is to evaluate the execution plan on each of the queries. 响应您的编辑,唯一确定哪种方法效果更好的唯一方法是评估每个查询的执行计划。 There are many factors that can come into determining the fastest approach and certainly the DBMS itself is one of those factors. 确定最快的方法有很多因素,DBMS本身就是其中之一。 A good query engine should be able to deduce the same or similar execution plan regardless of the approach. 一个好的查询引擎应该能够推断出相同或相似的执行计划,而不管采用哪种方法。 That said, using a derived table (ie approach #1) may be a bit more explicit to the query engine (even if less explicit to the reader of the query) and thus might perform better. 也就是说,使用派生表(即方法#1)对查询引擎可能会更明确(即使对查询的读取者而言不太明确),因此可能会表现更好。 Often it is the case that derived tables perform better than correlated subqueries (my solution and your approach #2). 通常情况下,派生表的性能要优于相关子查询(我的解决方案和您的方法2)。 However, I wouldn't alter the approach until I had evidence to support the change. 但是,在我有证据支持该更改之前,我不会更改方法。 Again, the only way to know which will perform better for certain is to evaluate the execution plan against your data. 同样,知道哪种方法在某些方面会更好的唯一方法是根据数据评估执行计划。

If you are using almost any database other than MySQL, then answer is to use ranking functions. 如果您正在使用MySQL以外的几乎所有数据库,那么答案是使用排名函数。 In particular, row_number does what you are looking for: 特别是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>)

Row number assigns a sequence nubmer to the records for each item. 行号为每个项目的记录分配一个序列数字。 It starts at 1 for the biggest reference date and then 2 for the next biggest and so on (based on the order by clause). 它从最大参考日期的1开始,然后从下一个最大参考日期的2开始,依此类推(基于order by子句)。 You want the first one, where seqnum = 1. 您需要第一个,其中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

Try this: 尝试这个:

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

It will select the MAX value from the columns holding the max(REFERENCEDATE). 它将从保存max(REFERENCEDATE)的列中选择MAX值。 If you only expect one column to have the max, then it would simply select from the one it can choose from. 如果仅希望一列具有最大值,则只需从它可以选择的那一列中进行选择。

This is the code you possibly need: 这是您可能需要的代码:

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
    )

You need to use a "join" with the table itself that refers to the record that has the maximum value for the same item . 您需要对表本身使用"join" ,以引用具有相同项目 最大值的记录。

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

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