2016-12-05 258 views
0

我有一张保留产品成本的表。我想获得平均成本上次购买每个产品的发票。选择的Oracle子查询

我的解决办法创造一个子选择来获得最后的购买发票但不幸的是我得到

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

+1

编辑您的问题,并提供样本数据和期望的结果。目前还不清楚你想要做什么。例如,哪列代表“价格”,“最后购买发票”是什么意思?什么专栏标识产品? –

+3

在版本12c之前的版本中,相关的子查询只能引用父级查询的一列。 “codprod = b.codprod”跨越两个等级,因此是错误。 –

+0

ROWNUM在子查询中不以这种方式工作。它适用于整个查询。您需要在外部查询中使用ROW_NUMBER()OVER(PARTITION BY c.valorultent ORDER BY c.dtultent DESC)AS row_no和WHERE row_no = 1。 – Doug

回答

1

您的问题是,您不能使用比一个子查询更深的别名列。根据评论,这在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中选取最上面的一行,这样就可以从您的子查询中获取最新/最旧/最大/最少/等。对于重复过滤也很有用。