2016-12-05 147 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中選取最上面的一行,這樣就可以從您的子查詢中獲取最新/最舊/最大/最少/等。對於重複過濾也很有用。