【问题标题】:Sub-select in oracleoracle中的子选择
【发布时间】:2011-04-21 16:58:34
【问题描述】:

我正在尝试从子选择中的另一个表中选择最新价格。但我不知道如何让它工作。

这是我尝试过的:

select something, somthingelse, 
  (
    select * from 
    (
      select QUOTE_PRICE as old_price
      from price_history
      where price_history.part_no= article_table.part_no
      order by valid_from desc
    ) where rownum=1
  )
from  article_table where rownum < 5

子选择自己工作,但找不到article_table.part_no

SQL 错误:ORA-00904:“article_table”。“part_no”:标识符无效

更新:

目前的解决方案:

select something, somethingelse, (
  SELECT MIN(QUOTE_PRICE) KEEP (DENSE_RANK FIRST ORDER BY valid_from)
  FROM price_history
  WHERE part_no=article_table.part_no
) as old_price
from  article_table a where rownum < 5

【问题讨论】:

    标签: sql oracle


    【解决方案1】:

    在 Oracle 中,子查询只能看到来自父查询的一级查询的值。由于您有两个嵌套选择,因此内部选择无法看到外部选择的值。

    您可以先执行连接:

    SELECT something, somthingelse, old_price
      FROM (SELECT a.something, a.somthingelse, p.quote_price old_price,
                   row_number() over (PARTITION BY a.part_no 
                                      ORDER BY valid_from DESC) rnk
               FROM article_table a
               LEFT JOIN price_history p ON a.part_no = p.part_no)
     WHERE rnk = 1;
    

    您还可以使用 PL/SQL 函数,当给定 article_table.part_no 时,该函数会从 price_history 返回第一个 quote_price

    【讨论】:

    • 行不通。我不想只选择一行。我想获取 article_table 中所有行的先前价格。还是我误解了你的建议?
    • @jgauffin : 运行查询 :) -- 查询将每 article_table 行返回一行。
    • 是的。谢谢。 +1。您如何看待我添加到问题中的解决方案?
    • @jgauffin:这是一个很好的解决“一级深度”限制的方法。它强制一种嵌套循环连接(概念上:获取一行,从另一个表中获取最大值,获取下一行......)所以如果你不从 article_table 获取很多行,它会执行得非常快(在你的情况它可能是最好的方法,因为你只返回 5 行)。在大型数据集的情况下,首先执行连接允许优化器从更大的访问路径集中进行选择,这可能会产生更有效的计划(特别是哈希连接)。
    • @Benoit:first_value 将在article_table 中每行返回 N 行(其中 N 是此 part_noprice_history 行数)。 N 行中的每一行都将具有相同的 old_price,因此您需要以某种方式对它们进行重复数据删除。你可以用 DISTINCT 来做,但我认为 RANK 方法更容易阅读——我使用 row_number 因为我不知道 (part_no, valid_from)price_history 中是否是唯一的。
    【解决方案2】:

    尝试在最外层查询中使用别名 article_table

    select a.something, a.somthingelse, 
      (
        select * from 
        (
          select QUOTE_PRICE as old_price
          from price_history
          where price_history.part_no= a.part_no
          order by valid_from desc
        ) where rownum=1
      )
    from  article_table a where rownum < 5
    

    此外,您可能希望研究 Oracle 分析函数,以便为此目的进行更简单的查询:

    http://psoug.org/reference/analytic_functions.html

    【讨论】:

    • 我要求取消删除您的答案,因为分析函数的链接有助于在我更新的答案中找到解决方案。如果我没有更清洁的解决方案,我会接受它。不要这么快就删除答案。
    • 如你所愿... :-) 我认为主要答案是错误的,分析函数也是由其他人提出的,所以我的回答对其他读者具有误导性...
    【解决方案3】:

    我会尝试以下方法:

    select something, somethingelse, last_value(quote_price) over (partition by part_no order by valid_from asc)
      from article_table inner join price_history using (part_no)
     where rownum < 5;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-23
      • 1970-01-01
      • 2018-09-01
      • 2018-04-03
      • 2015-06-16
      • 1970-01-01
      相关资源
      最近更新 更多