2017-04-12 151 views
1

下面的SQL被寫入以返回「打開的訂單」。這是以我能理解的方式編寫的,但現在我想嘗試優化並減少代碼量。縮短不使用公用表表達式的SQL語句

下面的SQL給了我期望的結果,但我希望縮短查詢而不使用WITH AS。任何使用UNION或其他嵌套方法的建議?

WITH 
product AS    --filter by dept 
    (SELECT item 
    , dept 
    FROM item_master 
    WHERE dept in ('353') 
), 
open_orders AS   --view of orders in Status A with ordered units > received units 
    (SELECT ol.order_no 
    , ol.item 
    , ol.location 
    , oh.po_type 
    , oh.order_type 
    , oh.not_before_date 
    , oh.not_after_date 
    , oh.otb_eow_date 
    , SUM(ol.qty_ordered) AS qty_ordered 
    , SUM(NVL(ol.qty_received,0)) AS qty_received 
    FROM ordhead oh 
    , ordloc ol 
    WHERE oh.order_no = ol.order_no 
    AND oh.status = 'A' 
    AND ol.qty_ordered > NVL(ol.qty_received,0) 
-- AND ol.order_no in ('18701212')  --optional filter for specific PO's 
    GROUP BY ol.order_no 
    , ol.item 
    , ol.location 
    , oh.po_type 
    , oh.order_type 
    , oh.not_before_date 
    , oh.not_after_date 
    , oh.otb_eow_date 
), 
allocations AS   --view of all allocations 
    (SELECT ah.alloc_no 
    , ah.order_no 
    , ah.item 
    , ad.to_loc 
    , NVL(ad.qty_allocated,0) AS qty_allocated 
    , NVL(ad.qty_received,0) AS qty_received 
    FROM alloc_header ah 
    , alloc_detail ad 
    WHERE ah.alloc_no = ad.alloc_no 
) 
SELECT p.dept  --main query on above views 
, oo.order_no 
, oo.po_type 
, oo.order_type 
, oo.not_before_date 
, oo.not_after_date 
, oo.otb_eow_date 
, oo.item 
, CASE WHEN oo.po_type = 0 THEN oo.location ELSE aa.to_loc END AS loc 
, SUM(oo.qty_ordered) AS order_qty 
, CASE WHEN SUM(NVL(aa.qty_allocated,0)) - SUM(NVL(aa.qty_received,0)) = 0 
    THEN SUM(oo.qty_ordered) - SUM(NVL(oo.qty_received,0)) 
    ELSE SUM(NVL(aa.qty_allocated,0)) - SUM(NVL(aa.qty_received,0)) 
    END AS open_qty 
FROM open_orders oo 
, allocations aa 
, product p 
WHERE oo.order_no = aa.order_no(+) 
AND oo.item = aa.item(+) 
AND oo.item = p.item 
AND (oo.qty_ordered - oo.qty_received) >0 
GROUP BY p.dept 
, oo.order_no 
, oo.po_type 
, oo.order_type 
, oo.not_before_date 
, oo.not_after_date 
, oo.otb_eow_date 
, oo.item 
, CASE WHEN oo.po_type = 0 THEN oo.location ELSE aa.to_loc END 
; 
+1

您使用的是什麼版本的SQL?我不介意那些'CASE'表達式,你爲什麼要改變它們? –

+4

_「這是用我能理解的方式編寫的,但現在我想嘗試優化並減少代碼量」因此,您想將您瞭解的代碼轉換爲代碼,而不是代碼中的代碼理解? –

+0

'UNION'會比情況更長,並且需要考慮多個場景,導致查詢時間太長,以至於幾乎不可讀 – JohnHC

回答

4

的CTE(公共表表達式)只是一個組織通過堅持的碼位的查詢(即定義一個「派生」表)在那可以在主語句重複使用頂部的方式。因此,在productopen_ordersallocationsFROM條款中提到的,你可以只換那些話了定義它們的代碼:

SELECT p.dept --main query on above views 
    , 
    oo.order_no, 
    oo.po_type, 
    oo.order_type, 
    oo.not_before_date, 
    oo.not_after_date, 
    oo.otb_eow_date, 
    oo.item, 
    CASE 
     WHEN oo.po_type = 0 
      THEN oo.location 
     ELSE aa.to_loc 
     END AS loc, 
    SUM(oo.qty_ordered) AS order_qty, 
    CASE 
     WHEN SUM(NVL(aa.qty_allocated, 0)) - SUM(NVL(aa.qty_received, 0)) = 0 
      THEN SUM(oo.qty_ordered) - SUM(NVL(oo.qty_received, 0)) 
     ELSE SUM(NVL(aa.qty_allocated, 0)) - SUM(NVL(aa.qty_received, 0)) 
     END AS open_qty 
FROM (
    SELECT ol.order_no, 
     ol.item, 
     ol.location, 
     oh.po_type, 
     oh.order_type, 
     oh.not_before_date, 
     oh.not_after_date, 
     oh.otb_eow_date, 
     SUM(ol.qty_ordered) AS qty_ordered, 
     SUM(NVL(ol.qty_received, 0)) AS qty_received 
    FROM ordhead oh, 
     ordloc ol 
    WHERE oh.order_no = ol.order_no 
     AND oh.STATUS = 'A' 
     AND ol.qty_ordered > NVL(ol.qty_received, 0) 
    -- AND ol.order_no in ('18701212')  --optional filter for specific PO's 
    GROUP BY ol.order_no, 
     ol.item, 
     ol.location, 
     oh.po_type, 
     oh.order_type, 
     oh.not_before_date, 
     oh.not_after_date, 
     oh.otb_eow_date 
    ) oo, 
    (
    SELECT ah.alloc_no, 
     ah.order_no, 
     ah.item, 
     ad.to_loc, 
     NVL(ad.qty_allocated, 0) AS qty_allocated, 
     NVL(ad.qty_received, 0) AS qty_received 
    FROM alloc_header ah, 
     alloc_detail ad 
    WHERE ah.alloc_no = ad.alloc_no 
    ) aa, 
    (
    SELECT item, 
     dept 
    FROM item_master 
    WHERE dept IN ('353') 
    ) p 
WHERE oo.order_no = aa.order_no(+) 
    AND oo.item = aa.item(+) 
    AND oo.item = p.item 
    AND (oo.qty_ordered - oo.qty_received) > 0 
GROUP BY p.dept, 
    oo.order_no, 
    oo.po_type, 
    oo.order_type, 
    oo.not_before_date, 
    oo.not_after_date, 
    oo.otb_eow_date, 
    oo.item, 
    CASE 
     WHEN oo.po_type = 0 
      THEN oo.location 
     ELSE aa.to_loc 
     END; 

這顯然不是縮短(而是由幾個字符) ,但我明白「縮短」不是你的要求。您正嘗試使此查詢在不支持CTE的產品中工作。

+0

謝謝,這正是我試圖解決的問題! –