使用子查询中的order更新以检索第一行

时间:2018-02-11 03:25:27

标签: sql oracle oracle11g

我正在尝试使用Oracle 11g从一组响应的第一行更新一个表的一列。我有一个表格,其中包含特定日期(cb_consumption)的特定产品的消费量,另外一张表格显示了几乎每天所有产品的价格变化 - 经过时间测量 - (cb_price)。我试着在最近的消费日期得到价格。 如果我这样做:

update cb_consumption t1 
set price = (select t2.price 
             from (select t2.price 
                   from cb_price t2 
                   where t2.id_product = t1.id_product 
                   order by abs(t2.elapsed_time - t1.elapsed_time) asc) 
             where rownum < 2);

我得到&#34;无效的标识符&#34;错误(ORA-00904)。似乎标识符不在子子查询中。 如果我这样做:

update cb_consumption t1 
set price = (select t2.price 
             from cb_price t2 
             where t2.id_product = t1.id_product 
             and rownum < 2
             order by abs(t2.elapsed_time - t1.elapsed_time) asc);

我得到&#34;错过右括号&#34;错误(ORA-00907)。似乎不可能使用&#34;顺序&#34;在子查询中。

我没有看到解决方案。如果你有想法。提前谢谢。

3 个答案:

答案 0 :(得分:1)

有办法!使用keep

update cb_consumption c
    set price = (select max(p.price) keep (dense_rank first order by abs(p.elapsed_time - c.elapsed_time))
                 from cb_price p
                 where p.id_product = c.id_product 
                );

Oracle仅识别直接子查询中的外部别名。在较低的筑巢水平下无法识别。

答案 1 :(得分:0)

如果出现错误(ORA-00904),则需要重新检查对象的名称(表格,列)。如果名称不匹配(大写/小写),那么它会抛出此错误。因为如果你把名字放在没有引号的地方,它就会区分大小写。要忽略它,您必须将对象名称放在引号内。

从错误(ORA-00907)开始是因为您在子查询中使用了ORDER BY子句,只有当您将ORDER BY放入视图时才支持Oracle,并在您的rownum = 1中包含WHERE UPDATE条款。因此,您的UPDATE CB_CONSUMPTION SET PRICE = ( SELECT PriceTotal FROM ( SELECT T2.PRICE AS PriceTotal FROM CB_PRICE T2 INNER JOIN CB_CONSUMPTION T1 ON T1.ID_PRODUCT = T2.ID_PRODUCT ORDER BY ABS(T2.ELAPSED_TIME - T1.ELAPSED_TIME) ASC ) WHERE ROWNUM = 1 ); 应该是这样的:

body {
  background-image: url('http:dev.doig.com.au/images/bg-page.jpg');
  background-size: cover;
  repeat: no-repeat;
}

#selector {
  list-style: none;
  max-width: 1322px;
  margin: 0 auto;
}

#selector li {
  display: inline-block;
  width: 11.625%;
  margin-right: 0.5%;
  margin-top: 1%;
  background-color: #012F60;
  height: 70px;
  display: inline-table;
}

#selector li:last-child {
  margin-right: 0%
}

#selector li#job.active {
  background-color: #93CB32;
}

#selector li a {
  color: white;
  text-align: center;
  vertical-align: middle;
  display: table-cell;
  text-decoration: none;
}

答案 2 :(得分:0)

第一个示例错误地将未命名的内联视图的price列引用为t2.price。您需要删除t2.或命名内联视图:

update cb_consumption t1 
set price = (select price  -- not t2.price
             from (select t2.price 
                   from cb_price t2 
                   where t2.id_product = t1.id_product 
                   order by abs(t2.elapsed_time - t1.elapsed_time) asc) 
             where rownum < 2);

update cb_consumption t1 
set price = (select t3.price 
             from (select t2.price 
                   from cb_price t2 
                   where t2.id_product = t1.id_product 
                   order by abs(t2.elapsed_time - t1.elapsed_time) asc) t3
             where rownum < 2);

您的第二个示例失败,因为单行子查询中不允许order by,例如updateselect (select)中的一个。您可以在其他子查询中使用order by

在Oracle 12.1中,如果包含row limiting clause

,它将变为有效
update cb_consumption t1 
set    price =
       ( select t2.price 
         from   cb_price t2 
         where  t2.id_product = t1.id_product 
         order by abs(t2.elapsed_time - t1.elapsed_time) asc
         fetch first row only );