[英]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.