oracle中的子选择

oracle中的子选择,oracle,limit,subquery,Oracle,Limit,Subquery,我正在与甲骨文中的一个subselect进行斗争。我想把另一张表上的最新价格包括在内 以下是我目前的尝试: SELECT tab1.* (select price from old_prices where part_no=tab1.article_no order by valid_from desc) as old_price, FROM articles tab1 order by article_no sub-select返回几行,我认为这就

我正在与甲骨文中的一个subselect进行斗争。我想把另一张表上的最新价格包括在内

以下是我目前的尝试:

SELECT tab1.*
    (select price from 
      old_prices 
    where part_no=tab1.article_no 
     order by valid_from desc) as old_price,
FROM articles tab1
order by article_no
sub-select返回几行,我认为这就是问题所在。但是我不知道如何限制Oracle中的行数。

限制行的使用。这是一个伪列,返回结果集每行的行号

编辑:

您需要添加另一个子选择查询(希望这是适合您需要的地方)

效率更高的是

SELECT 
    tab1.*
  , P.price
FROM 
    articles tab1
  , ( SELECT 
          part_no
        , price
        , row_number () over (partition by part_no order by valid_from desc ) rn
      FROM
          old_prices
    ) P 
WHERE 
  P.part_no(+) = tab1.article_no
  P.rn(+)      = 1
;

如果是您追求的最新价格:

SELECT tab1.*, p.price old_price
FROM articles tab1
,    old_prices p
where p.part_no = tab1.article_no
and valid_from = (
    select MAX(valid_from)
    from   old_prices p2
    where  p2.part_no = p.part_no
)
order by article_no
我想包括最新的价格

我想你指的是最新的

好的,首先这有点问题,有几种方法:

SELECT o.price
FROM old_prices o
WHERE o.part_no=&part_no
AND o.ondate=(SELECT MAX(o2.ondate)
     FROM old_prices o2
     WHERE o2.part_no=&part_no);
这似乎是最明显的选择,但它的效率相当低

你可以试试

SELECT ilv.price
FROM (SELECT o.price 
   FROM old_price o
   WHERE o.part_no=&part_no
   ORDER BY ondate DESC) ilv
WHERE rownum=1;
或者

SELECT TO_NUMBER(
   SUBSTR(
      MAX(TO_CHAR(o.ondate, 'YYYYMMDDHH24MISS') || price)
      , 15)
   ) as latest_price
FROM old_price o
WHERE o.part_no=&part_no;
问候,

Rob。

问题是我不知道如何在我的子选择中使用它,因为它必须在DESC有效的
订单之后(或者我不会得到最新的价格)我得到
“TAB1”。“article\u no”:是未知标识符
也许你不需要
文章的
TAB1
别名?您可以尝试不使用它吗?
在第一个示例的内部联接中找不到文章号
,第二个示例的问题是,我在查询中使用了一些其他联接,无法混合(
老式外部联接(+)不能与ANSI联接一起使用
)@jgauffin:如果您可以确保每个文章条目至少有一个旧价格条目,那么您可以使用内部联接(不带(+))。否则,结果集将不包含旧版本中没有相应条目的项目行_prices@jgauffin:我已编辑答案中的第一个选择。您可以尝试这个新版本:)@jgauffin&表示SQL*Plus替换变量。详情如下:
SELECT ilv.price
FROM (SELECT o.price 
   FROM old_price o
   WHERE o.part_no=&part_no
   ORDER BY ondate DESC) ilv
WHERE rownum=1;
SELECT TO_NUMBER(
   SUBSTR(
      MAX(TO_CHAR(o.ondate, 'YYYYMMDDHH24MISS') || price)
      , 15)
   ) as latest_price
FROM old_price o
WHERE o.part_no=&part_no;
SQL> create table articles (article_no,name)
  2  as
  3  select 1, 'PEN' from dual union all
  4  select 2, 'PAPER' from dual
  5  /

Table created.

SQL> create table old_prices (part_no,valid_from,price)
  2  as
  3  select 1, date '2008-01-01', 10 from dual union all
  4  select 1, date '2009-01-01', 11 from dual union all
  5  select 1, date '2010-01-01', 12 from dual union all
  6  select 1, date '2011-01-01', 13 from dual union all
  7  select 2, date '2010-01-01', 89.95 from dual union all
  8  select 2, date '2011-01-01', 94.95 from dual union all
  9  select 2, date '2012-01-01', 99.95 from dual
 10  /

Table created.

SQL> select a.article_no
  2       , max(a.name) keep (dense_rank last order by p.valid_from) name
  3       , max(p.price) keep (dense_rank last order by p.valid_from) price
  4    from articles a
  5       , old_prices p
  6   where a.article_no = p.part_no
  7   group by a.article_no
  8  /

ARTICLE_NO NAME       PRICE
---------- ----- ----------
         1 PEN           13
         2 PAPER      99.95

2 rows selected.
with old_prices as(
select level * 15 price ,
       mod (level ,5) part_no , --this is just to create a grouping type partno
       (sysdate - level ) valid_from
  from dual
connect by level < 100) 
  ,
articles as(
     select level , 
            mod(level , 5 ) article_no ,
            (sysdate + level) someOtherDateField
    From dual
    connect by level < 5
     )
SELECT tab1.* ,
       old_price.*
  from articles tab1 
       left join
       (
         select price,
                part_no ,
                valid_from ,
                rank() over(partition by part_no order by valid_from desc) rk
          from old_prices
       ) old_price
       on tab1.article_no = old_price.part_no
          and old_price.rk = 1
order by article_no ;
LEVEL                  ARTICLE_NO             SOMEOTHERDATEFIELD        PRICE                  PART_NO                VALID_FROM                RK                     
---------------------- ---------------------- ------------------------- ---------------------- ---------------------- ------------------------- ---------------------- 
1                      1                      25/05/11 07:30:54         15                     1                      23/05/11 07:30:54         1                      
2                      2                      26/05/11 07:30:54         30                     2                      22/05/11 07:30:54         1                      
3                      3                      27/05/11 07:30:54         45                     3                      21/05/11 07:30:54         1                      
4                      4                      28/05/11 07:30:54         60                     4                      20/05/11 07:30:54         1