oracle中的子选择
我正在与甲骨文中的一个subselect进行斗争。我想把另一张表上的最新价格包括在内 以下是我目前的尝试: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返回几行,我认为这就
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