2017-04-12 98 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

谢谢,这正是我试图解决的问题! –