【问题标题】:Oracle subquery in select选择中的 Oracle 子查询
【发布时间】:2016-12-05 13:09:20
【问题描述】:

我有一张记录产品成本的表格。我想获得每种产品的平均成本最后一次购买发票。

我的解决方案是创建一个子选择以获取最后一次购买发票,但不幸的是我得到了

ORA-00904: "B"."CODPROD": invalid identifier

我的查询是

SELECT  (b.cod_aux) product,
    -- here goes code to get average cost,
    (SELECT round(valorultent, 2) 
     FROM (SELECT valorultent
           FROM pchistest
           WHERE codprod = b.codprod
           ORDER BY dtultent DESC) 
     WHERE ROWNUM = 1)
FROM pchistest a, pcembalagem b
WHERE a.codprod = b.codprod
GROUP BY a.codprod, b.cod_aux
ORDER BY b.cod_aux

简而言之,我在 sub-select 上所做的是按顺序排序并在给定产品 b.codprod 的情况下获得第一行

【问题讨论】:

  • 编辑您的问题并提供示例数据和所需的结果。目前尚不清楚您想做什么。例如,哪些列代表“价格”,“最后购买发票”是什么意思?哪一列标识了产品?
  • 在 12c 版本之前的版本中,相关子查询只能引用上一级父查询的列。 codprod = b.codprod 跨越两个级别,因此错误。
  • ROWNUM 在子查询中不能以这种方式工作。它适用于整个查询。您需要在外部查询中使用 ROW_NUMBER() OVER (PARTITION BY c.valorultent ORDER BY c.dtultent DESC) AS row_no 和 WHERE row_no = 1。
  • 为什么不能使用最小/最大函数?取决于dtultent 可以有什么值..
  • @Doug rownum 适用于查询块。如果在子查询中使用它,它适用于子查询而不是“整个查询”。但这不是 OP 出现该错误的原因。

标签: sql oracle oracle11g subquery


【解决方案1】:

您的问题是您不能使用比一个子查询更深的别名列。据cmets说,这是在12C的时候改的,但是我没有机会尝试,因为我使用的数据仓库还在11g上。

我会使用这样的东西:

SELECT b.cod_aux AS product
      ,ROUND (r.valorultent, 2) AS valorultent
FROM pchistest a
JOIN pcembalagem b ON (a.codprod = b.codprod)
JOIN (SELECT valorultent
            ,codprod
            ,ROW_NUMBER() OVER (PARTITION BY codprod
                                    ORDER BY dtultent DESC)
            AS row_no
      FROM pchistest) r ON (r.row_no = 1 AND r.codprod = b.codprod)
GROUP BY a.codprod, b.cod_aux
ORDER BY b.cod_aux

我避免在 SELECT 语句中进行子查询。大多数时候,优化器希望为游标中的每个项目运行一个 SELECT,或者它执行一些疯狂的嵌套循环。如果您将其作为 JOIN 中的子查询来执行,Oracle 通常会处理您要连接的行;通常,它更有效。最后,在最终产品中完成每个项目的功能(在本例中为 ROUND)。这将阻止 Oracle 在所有行上执行此操作,而不仅仅是您使用的行。它应该正确地执行此操作,但它可能会在复杂的查询中感到困惑。

ROW_NUMBER() OVER (PARTITION BY ..) 是魔法发生的地方。这会为每组 CODPROD 添加一个行号。这允许您从每个 CODPROD 中提取第一行,因此这允许您从子查询中获取最新/最旧/最大/最少/等。它也非常适合过滤重复。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-03-26
    • 2013-12-21
    • 2021-09-27
    • 2020-06-13
    • 2021-10-15
    • 1970-01-01
    • 2012-04-15
    相关资源
    最近更新 更多