我怎样才能优化这个动态SQL查询?

时间:2013-02-03 08:05:14

标签: sql oracle select union

我在使用以下查询时遇到了困难。我一直在努力优化它,也许会让它更具可读性。假设我有3个表orders_returned,orders_completed,orders_delivered,匹配列oder_id,customer_id。根据所选的选项,我可能需要检索已交付的订单,然后返回并最终完成(所有三个表中都出现相同的order_id),这些订单具有相同的customer_id。此外,我可能只需要检索已交付和已退回的订单,在这种情况下,我将从 WHERE 子句中省略 AND order_id IN (SELECT order_id FROM ORDERS_COMPLETED) 。例如,客户John和Tim 获取交付订单并返回订单 截至目前,我的查询如下所示:

SELECT order_id
FROM
(
    SELECT order_id, customer_id
    FROM ORDERS_RETURNED
    UNION
    SELECT order_id, customer_id
    FROM ORDERS_COMPLETED
    UNION
    SELECT order_id, customer_id
    FROM ORDERS_DELIVERED
)
WHERE 
    customer_id IN ('customer1', 'customer2', ...)
    AND order_id IN (SELECT order_id FROM ORDERS_RETURNED)
    AND order_id IN (SELECT order_id FROM ORDERS_COMPLETED)
    AND order_id IN (SELECT order_id FROM ORDERS_DELIVERED)

我还在学习SQL,想看看是否有更好的选择。

编辑:我正在使用Oracle数据库。还有Orders表,它具有不同的order_id和一些其他不相关的列。它不存储customer_ids。 此外,订单可能只出现在一个表中,也可能只出现在两个表中,因此我认为连接在这里没用。

3 个答案:

答案 0 :(得分:2)

由于您有一个Order表,我认为您也将CustomerId存储在该表中。假设是这样,试试这个:

SELECT DISTINCT O.OrderId
FROM Orders O
   LEFT JOIN Orders_Completed OC ON O.OrderId = OC.OrderId
   LEFT JOIN Orders_Delivered OD ON O.OrderId = OD.OrderId
   LEFT JOIN Orders_Returned ORE ON O.OrderId = ORE.OrderId
WHERE O.CustomerId IN (...)
   AND OD.OrderId IS NOT NULL AND ORE.OrderId IS NOT NULL AND OC.OrderId IS NULL

此特定查询将返回所有不同的订单,其中客户在(...)订单已交付并退回但尚未完成。切换使用IS NULL和IS NOT NULL来获得所需的输出。

祝你好运。

答案 1 :(得分:0)

您应该使用联接而不是内部/嵌套查询。

请尝试以下代码::

SELECT A.order_id, A.customer_id FROM ORDERS_RETURNED A 
INNER JOIN ORDERS_COMPLETED B ON A.order_id = B.order_id AND A.customer_id = B.customer_id
INNER JOIN ORDERS_DELIVERED C ON A.order_id = C.order_id AND A.customer_id = C.customer_id
Where A.customer_id IN ('customer1', 'customer2', ...)

答案 2 :(得分:0)

你可以这样做:

with data
     as (select customer_id,
                order_id,
                nvl(max(case status when 'RETURNED' then 'Y' end), 'N') returned,
                nvl(max(case status when 'COMPLETED' then 'Y' end), 'N') completed,
                nvl(max(case status when 'DELIVERED' then 'Y' end), 'N') delivered
           from (select 'RETURNED' status, order_id, customer_id
                   from orders_returned
                 union all
                 select 'COMPLETED' status, order_id, customer_id
                   from orders_completed
                 union all
                 select 'DELIVERED' status, order_id, customer_id
                   from orders_delivered)
          group by customer_id, order_id)
select *
  from data
 where returned = 'Y'
   and delivered = 'Y'
   and customer_id in ('xx', 'xxx') ;

with data
     as (select customer_id,
                order_id,
                max(returned) returned,
                max(completed) completed,
                max(delivered) delivered
           from (select 'Y' returned, null completed, null delivered, order_id, customer_id
                   from orders_returned
                 union all
                 select null, 'Y', null, order_id, customer_id
                   from orders_completed
                 union all
                 select null, null, 'Y', order_id, customer_id
                   from orders_delivered)
          group by customer_id, order_id)
select *

来自数据  返回的地方='Y'    并且交付='Y'    和customer_id in('xx','xxx');

例如:http://sqlfiddle.com/#!4/3e2fb/2