2013-02-03 26 views
0

我一直遇到以下问题。我一直在试图优化它,或许使它更具可读性。假设我有3个表orders_returned,orders_completed,orders_delivered与匹配列oder_id,customer_id。根据选定的选项,我可能需要检索已交付的订单,然后返回并最终完成(具有相同customer_id的所有三个表中相同的order_id)。此外,我可能只需要检索只发货和退货的订单,在这种情况下,我将省略AND order_id IN (SELECT order_id FROM ORDERS_COMPLETED)WHERE条款。例如,获取传递和返回客户约翰和蒂姆· 订单截至目前我的查询看起来是这样的:我如何优化这个动态SQL查询?

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数据库。还有订单表有不同的order_ids和一些其他不相关的列。它不存储customer_ids。 此外,订单可能发生在一张表中或两张中,所以我认为这些连接在这里没有用处。

+0

您使用的是什么RDBMS? – sgeddes

+0

您是否没有存储所有DISTINCT订单的订单表? – sgeddes

+0

我正在使用Oracle。是的,有订单表与不同的order_id's。 –

回答

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', ...) 
+0

是的,我想过内部连接。问题是,订单可能记录在交货表中,而其他所有订单都不存在,我认为这只会显示所有三个表中的订单? –

2

既然你有一个订单表,我想你也存储在客户在该表也是如此。假设如此,试试这个:

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来获得所需的输出。

祝你好运。从数据

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' 和('XX交付= 'Y' 和CUSTOMER_ID:

+0

谢谢,但不幸的是,customer_id不在同一张表中。 –

+0

然后,如果您没有任何与客户订单匹配的表,则您可以重新使用UNION获取该信息... – sgeddes

+0

@JR - 您的'订单'表没有'customer_id',但是其他表呢?这看起来很奇怪,因为所有这三个看起来像他们稍后会填充'订单',并且提出一个规范化问题。你有另外一张表格可以将客户与订单联系起来 - 'customer_orders'可能吗?如果是的话,你也可以加入到这个中? –