繁体   English   中英

选择中的Oracle子查询

[英]Oracle subquery in select

我有一张桌子,用来保存产品成本。 我想获取每种产品的平均费用最后购买的发票。

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

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

简而言之,我在子选择上所做的工作是b.codprod排序,并给出给定产品b.codprod的第一行

您的问题是您使用的别名列不能超过一个子查询。 根据评论,这在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中选出第一行,因此可以从子查询中获取最新/最旧/最大/最小/等。 这对于过滤重复项也很有用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM