2011-05-24 103 views
0

我與Oracle中的子查詢中掙扎。我想包括另一張表的最新價格。子選擇在Oracle

這裏是我當前的嘗試:

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 

子select返回幾行我認爲這是問題。但我不知道如何限制Oracle中的行數。

回答

2
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. 

問候,
羅布。

0

要限制行使用ROWNUM < 10。這是一個僞列,返回結果集每行的行號。

編輯:

您需要添加其他的子查詢中查詢(希望這是你需要正確的地方)

SELECT tab1.* 
    select (
    (select price from old_prices 
     where part_no=tab1.article_no order by valid_from desc 
    ) as x 
    where rownum = 1 
) as old_price 
FROM articles tab1 
order by article_no 
+1

或許'這裏的rownum = 1',因爲他只想一排... – forsvarir 2011-05-24 08:34:37

+0

的問題是,我不知道如何使用它在我的子查詢,因爲它必須是'ORDER BY VALID_FROM後DESC'(或者我不會得到最新的價格) – jgauffin 2011-05-24 08:36:39

+0

我得到''TAB1「。」article_no「:是一個未知的標識符 – jgauffin 2011-05-24 09:01:53

0
SELECT tab1.* 
    (select 
     price 
    from (
      SELECT 
       part_no 
      , price 
      , row_number() over (partition by part_no order by valid_from desc) rn 
      FROM 
      old_prices 
      ) P 
     where rn =1 
     and tab1.article_no = P.part_no 
    )            as old_price 
FROM articles tab1 
order by article_no 

更有效的將是

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 
; 
+0

'article_no'沒有在內部發現加入的第一個例子,並與第二個例子的問題是,我的用戶一些其他的在我的查詢連接,我不能混用('舊風格的外連接(+)不能與ANSI使用joins') – jgauffin 2011-05-24 09:41:37

+0

@jgauffin:如果你能確保每個物品入境有在old_prices至少一個條目,比你可以使用內部連接(無(+))。否則,結果集不會包含old_prices中沒有相應條目的文章的行 – schurik 2011-05-24 09:56:58

+0

@jgauffin:我已編輯我的答案中的第一個選擇。你可以試試這個新版本:) – schurik 2011-05-24 10:08:26

0

如果這是你後的最新價格:

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 
0

我想包括最新的價格

我想你的意思是最新的。

OK,很好,有點下手的問題,也有這樣做的幾種方法:

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

似乎是最明智的選擇,但其相當innefficient。

你可以試試....

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; 
+0

'&'做什麼? – jgauffin 2011-05-24 09:03:10

+0

@jgauffin&代表SQL * Plus替換變量。詳情在這裏:http://download.oracle.com/docs/cd/B19306_01/server.102/b14357/ch5.htm#sthref1031 – 2011-05-24 12:29:04

0
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