2012-11-13 53 views
0

我有以下表格,它代表项目的估值。如何检索对应于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的教程,我最终设法希望SQL服务器会理解的

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

全部我需要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的估值?

注:我需要工作至少在甲骨文的解决方案和SQL Server

编辑:谢谢大家的帮助。我被困在一个洞中,试图逃脱只有一个SELECT ... GROUP BY请求。现在我看到有一些阐明围绕着同样的想法两种方法:

  1. 制作与其他独立的请求的结果,将返回所有的项目/ MAX(日期)夫妇
  2. 使用子请求结果的JOIN在where子句中,每个item都会有不同的值。

有人可以提供一个理由(或指向一个理由)更喜欢一个到另一个?

+0

关于你的问题哪个解决方案更好:你将不得不比较每个解决方案的执行计划。它在很大程度上取决于查询优化器,定义的索引和涉及的数据。 –

回答

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 
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)列中的最大值。如果您只希望一列具有最大值,那么只需从它可以选择的列中进行选择即可。

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)执行得更好。但是,除非我有证据支持这一变化,否则我不会改变方法。再一次,要知道哪些方法可以更好地执行某些功能的唯一方法是根据您的数据评估执行计划。

+0

感谢您的回答,它的工作原理。你能否看到我的编辑和帮助指出我们有两个更好的选择之一的原因。 –

+0

@SamuelRossille - 完成。然而,Gordon Linoff的方法代表了第三种方法,即使用排名功能。 – Thomas

-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"与表本身是指具有同一项目最大值记录。

+0

我没有downvote。只是可能“SELECT *”被认为是不好的做法,因为如果将列添加到表中,结果是不稳定的。除此之外,没有看到任何明显的失望原因。只是不要个人承担...这只是一个问答网站。 –

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>) 

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

相关问题