0

我有下表,代表物品的估价。

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 用于实现当前结果行上表示的项目的 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 子句中使用子请求会导致每个项目具有不同的值。

任何人都可以提供一个理由(或指向一个理由的指针)来更喜欢另一个吗?

4

5 回答 5

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 小提琴版本

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

于 2012-11-13T20:09:27.683 回答
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>)

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

于 2012-11-13T20:53:27.383 回答
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
于 2012-11-13T20:15:15.210 回答
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

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

于 2012-11-13T20:08:51.367 回答
-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
    )

您需要将 a"join"与表本身一起使用,该表引用具有同一项目最大值的记录。

于 2012-11-13T20:12:51.537 回答