简体   繁体   English

选择中的Oracle子查询

[英]Oracle subquery in select

I have a table that keeps costs of products. 我有一张桌子,用来保存产品成本。 I'd like to get the average cost AND last buying invoice for each product. 我想获取每种产品的平均费用最后购买的发票。

My solution was creating a sub-select to get last buying invoice but unfortunately I'm getting 我的解决方案是创建一个子选择,以获取最后的购买发票,但不幸的是,我得到了

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

My query is 我的查询是

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

In short what I'm doing on sub-select is ordering descendantly and getting the first row given the product b.codprod 简而言之,我在子选择上所做的工作是b.codprod排序,并给出给定产品b.codprod的第一行

Your problem is that you can't use your aliased columns deeper than one sub-query. 您的问题是您使用的别名列不能超过一个子查询。 According to the comments, this was changed in 12C, but I haven't had a chance to try it as the data warehouse that I use is still on 11g. 根据评论,这在12C中已更改,但是由于我使用的数据仓库仍在11g上,因此我没有机会尝试它。

I would use something like this: 我会用这样的东西:

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

I avoid sub-queries in SELECT statements. 我避免在SELECT语句中使用子查询。 Most of the time, the optimizer wants to run a SELECT for each item in the cursor, OR it does some crazy nested loops. 大多数时候,优化器希望为游标中的每个项目运行一个SELECT,或者它会执行一些疯狂的嵌套循环。 If you do it as a sub-query in the JOIN, Oracle will normally process the rows that you are joining; 如果您在JOIN中将其作为子查询来执行,则Oracle通常会处理您要加入的行。 normally, it is more efficient. 通常,它效率更高。 Finally, complete your per item functions (in this case, the ROUND) in the final product. 最后,在最终产品中完成每个项目的功能(在这种情况下为ROUND)。 This will prevent Oracle from doing it on ALL rows, not just the ones you use. 这将阻止Oracle在所有行上执行此操作,而不仅仅是在您使用的行上执行。 It should do it correctly, but it can get confused on complex queries. 它应该正确执行此操作,但是在复杂的查询中可能会造成混淆。

The ROW_NUMBER() OVER (PARTITION BY ..) is where the magic happens. 发生魔术的地方是ROW_NUMBER()OVER(PARTITION BY ..)。 This adds a row number to each group of CODPRODs. 这会向每组CODPROD添加行号。 This allows you to pluck the top row from each CODPROD, so this allows you to get the newest/oldest/greatest/least/etc from your sub-query. 这使您可以从每个CODPROD中选出第一行,因此可以从子查询中获取最新/最旧/最大/最小/等。 It is also great for filtering duplicates. 这对于过滤重复项也很有用。

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

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