针对已取消的订单优化SQL查询

时间:2009-11-20 16:26:27

标签: sql database query-optimization

以下是我的表格的一部分:

orders:
 - order_id
 - customer_id

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

我想为给定客户(customer_id)选择所有订单(order_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
)

6 个答案:

答案 0 :(得分: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)

答案 1 :(得分: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当且仅当有一些产品并且它们都被取消时才会返回。{/ p>

如果根本没有产品,子查询将返回NULL;如果至少有一个非抽样产品,子查询将返回1

确保您在order_products (order_id, canceled)

上有索引

答案 2 :(得分: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

答案 3 :(得分: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

答案 4 :(得分: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)

答案 5 :(得分: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);