缩短不使用公用表表达式的SQL语句

时间:2017-04-12 12:47:13

标签: sql oracle

下面的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 个答案:

答案 0 :(得分:4)

CTE(公用表表达式)只是一种组织查询的方法,它通过在顶部添加可以在主语句中重用的代码(定义“派生”表)。因此,product子句中提到open_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的产品中工作。