2012-05-23 122 views
0

在Oracle 9.2.0.8中,我需要返回一个特定字段(LAB_SEQ)最大的记录集(它是一个连续的VARCHAR数组'0001','0002'等)对于每个另一个字段(WO_NUM)。要选择最大值,我试图按降序排列并选择第一行。我在StackOverflow上找到的所有东西都表明,唯一的方法是使用相关的子查询。然后,我用这个最大外部查询的WHERE子句中得到我想要每个WO_NUM行:在Oracle中避免相关子查询

SELECT lt.WO_NUM, lt.EMP_NUM, lt.LAB_END_DATE, lt.LAB_END_TIME 
FROM LAB_TIM lt WHERE lt.LAB_SEQ = (
    SELECT LAB_SEQ FROM (
     SELECT lab.LAB_SEQ FROM LAB_TIM lab WHERE lab.CCN='1' AND MAS_LOC='1' 
      AND lt.WO_NUM = lab.WO_NUM ORDER BY ROWNUM DESC 
    ) WHERE ROWNUM=1 
) 

然而,这个返回lt.WO_NUM错误的无效的标识符。研究表明,ORACLE 8只允许相关的子查询达到一个深度,并且建议重写以避免子查询 - 这是关于选择最大值的讨论暗示无法完成的事情。任何帮助得到这个声明执行将不胜感激。

+3

由ROWNUM订购在这里并不是非常有用。 – DCookie

回答

3

你的相关子查询将需要像

SELECT lt.WO_NUM, lt.EMP_NUM, lt.LAB_END_DATE, lt.LAB_END_TIME 
FROM LAB_TIM lt WHERE lt.LAB_SEQ = (
    SELECT max(lab.LAB_SEQ) 
    FROM LAB_TIM lab 
    WHERE lab.CCN='1' AND MAS_LOC='1' 
     AND lt.WO_NUM = lab.WO_NUM 
) 

既然你是在Oracle 9.2,它可能会更有效地使用相关子查询。我不确定lab.CCN='1' AND MAS_LOC='1'谓词在当前查询中的作用,所以我不太确定如何将它们转换为分析函数方法。 中LAB_SEQWO_NUM的组合不唯一吗?您是否需要在CCNMAS_LOC的谓词中添加以便为每个WO_NUM获取一个唯一的行?还是你使用这些谓词来减少输出中的行数?其基本做法会像

SELECT * 
    FROM (SELECT lt.WO_NUM, 
       lt.EMP_NUM, 
       lt.LAB_END_DATE, 
       lt.LAB_END_TIME, 
       rank() over (partition by wo_num 
           order by lab_seq desc) rnk 
      FROM LAB_TIM lt) 
    WHERE rnk = 1 

,但它不是很清楚,我是否CCNMAS_LOC需要被添加到ORDER BY子句中的解析函数或是否需要添加到WHERE条款。

+1

+1,虽然8i已经有[analytics](http://docs.oracle.com/cd/A87860_01/doc/server.817/a85397/function.htm#81409):) –

+0

@VincentMalgrat - 你说得对 - 看起来像8.1.6中介绍的那样。 –

+0

谢谢,贾斯汀。虽然这实现了我的目标,但却遭受了严重的低效率。由于max()函数会迭代表中的每个条目(这很大),所以我想利用这样的事实,即行实际上是按顺序排列的。我认为ROWNUM的排序比LAB_SEQ更有效,因为比较字符串非常耗时。您建议的查询现在已经运行了大约5分钟,看不到任何结果。 – user1412922

0

这是相关子查询更好的一种情况,特别是在表上有索引的情况下。但是,应该可以将相关的子查询重写为连接。

我认为下面是等价的,不相关子查询:

SELECT lt.WO_NUM, lt.EMP_NUM, lt.LAB_END_DATE, lt.LAB_END_TIME 
FROM (select *, rownum as r 
     from LAB_TIM lt 
    ) lt join 
    (select wo_num, max(r) as maxrownum 
     from (select LAB_SEQ, wo_num, rownum as r 
      from LAB_TIM lt 
      where lab.CCN = '1' AND MAS_LOC = '1' 
      ) 
    ) ltsum 
    on lt.wo_num = ltsum.wo_num and 
     lt.r = ltsum.maxrownum 

我有点不确定甲骨文如何处理的事情rownums像ORDER BY。