2009-11-20 135 views
2

這裏是我的表的子集:優化SQL查詢取消訂單

orders: 
- order_id 
- customer_id 

order_products: 
- order_id 
- order_product_id (unique key) 
- canceled 

我想選擇一個給定客戶的所有訂單(ORDER_ID)(CUSTOMER_ID),所有的產品訂單都是取消了,不僅僅是一些產品。是否有這樣做比這更優雅的或有效的方法:

select order_id from orders 
where order_id in (
    select order_id from orders 
    inner join order_products on orders.order_id = order_products.order_id 
    where order_products.customer_id = 1234 and order_products.canceled = 1 
) 
and order_id not in (
    select order_id from orders 
    inner join order_products on orders.order_id = order_products.order_id 
    where order_products.customer_id = 1234 and order_products.canceled = 0 
) 
+2

什麼數據庫引擎,您使用的,即MySQL和SQL服務器-2000,SQL服務器2005,Oracle等 – chadhoc 2009-11-20 16:31:20

回答

2

如果所有訂單都在order_products至少一行,試試這個

Select order_id from orders o 
Where Not Exists 
     (Select * From order_products 
     Where order_id = o.order_id 
      And cancelled = 1) 

如果上述假設是不正確的,那麼您還需要:

Select order_id from orders o 
Where Exists 
     (Select * From order_products 
     Where order_id = o.order_id) 
    And Not Exists 
     (Select * From order_products 
     Where order_id = o.order_id 
      And cancelled = 1) 
0
SELECT customer_id, order_id, count(*) AS product_count, sum(canceled) AS canceled_count 
FROM orders JOIN order_products 
ON orders.order_id = order_products.order_id 
WHERE customer_id = <<VALUE>> 
GROUP BY customer_id, order_id 
HAVING product_count = canceled_count 
1

最快的方式將是這樣的:

SELECT order_id 
FROM orders o 
WHERE customer_id = 1234 
     AND 
     (
     SELECT canceled 
     FROM order_products op 
     WHERE op.order_id = o.order_id 
     ORDER BY 
       canceled DESC 
     LIMIT 1 
     ) = 0 

子查詢將返回0當且僅當已經有一些產品,他們都被取消。

如果根本沒有產品,子查詢將返回NULL;如果至少有一個未被取消的產品,子查詢將返回1

確保您有order_products (order_id, canceled)

1

像這樣的指標?這假設每個訂單至少有一個產品,否則此查詢將返回沒有任何產品的訂單。

select order_id 
from orders o 
where not exists (select 1 from order_products op 
        where canceled = 0 
        and op.order_id = o.order_id 
) 
and o.customer_id = 1234 
0

你可以嘗試這樣的事情

select orders.order_id 
from @orders orders inner join 
     @order_products order_products on orders.order_id = order_products.order_id 
where order_products.customer_id = 1234 
GROUP BY orders.order_id 
HAVING SUM(order_products.canceled) = COUNT(order_products.canceled) 
0

因爲我們不知道的數據庫平臺,這裏是一個ANSI標準方法。請注意,這不會假定架構(即取消字段的數據類型,如何設置取消標誌(即'YES',1等)),並且沒有針對特定的數據庫平臺使用任何特定的數據庫平臺(這可能是更有效的方法,如果你可以給我們的平臺和版本您正在使用):

select op1.order_id 
from (
      select op.order_id, cast(case when op.cancelled is not null then 1 else 0 end as tinyint) as is_cancelled 
      from #order_products op 
     ) op1 
group by op1.order_id 
having count(*) = sum(op1.is_cancelled);