oracle中的子选择

发布于 2024-11-09 04:56:52 字数 309 浏览 0 评论 0原文

我正在与 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

子选择返回几行,我认为这是问题所在。但我不知道如何限制Oracle中的行数。

I'm struggling with a subselect in oracle. I want to include the latest price from another table.

Here is my current attempt:

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

The sub select returns several rows which I think is the problem. But I do not know how to limit the number of rows in Oracle.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

与酒说心事 2024-11-16 04:56:52
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.

问候,
抢。

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.

Regards,
Rob.

厌倦 2024-11-16 04:56:52

如果您要的是最新价格:

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

If it's the latest price you're after:

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
旧城空念 2024-11-16 04:56:52

我想包含最新价格

我想你指的是最新价格。

好吧,一开始这有点问题,有几种方法可以做到这一点:

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;

I want to include the lastest price

I presume you mean latest.

OK, well that's a bit of a problem to start with, there are several ways of doing this:

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

Seems the most obvious choice but its rather innefficient.

You could try....

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;

Or....

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;
罗罗贝儿 2024-11-16 04:56:52

要限制行数,请使用 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

To limit rows use ROWNUM < 10. This is a pseudocolumn returning the row number of each line of your resultset.

EDIT:

You need to add another subselect query (hope this is the right place for your need)

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
忆依然 2024-11-16 04:56:52
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
;
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

more efficient would be

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
;
无远思近则忧 2024-11-16 04:56:52
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
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 ;

Here's another way!

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文