获得最大和最小订单数量的客户的更好方法

时间:2014-01-15 19:21:05

标签: mysql

我的问题是找到所有那些已经达到最低和最高无订单的客户。

我能想出的是:

select customer_id , count(order_id) as num 
from bab_customer right outer join bab_order_details using(customer_id)
group by customer_id
having count(order_id) >= 
    all(select count(order_id) 
        from bab_customer right outer join bab_order_details using(customer_id)
        group by customer_id)
or count(order_id) <= 
    all(select count(order_id) 
        from bab_customer right outer join bab_order_details using(customer_id)
        group by customer_id);

它给了我正确的输出,但我必须做同样的连接3次。有更好的方法吗?

3 个答案:

答案 0 :(得分:2)

这样更好吗?我不知道......

SELECT x.* 
  FROM 
     ( SELECT customer_id
            , COUNT(*) cnt 
         FROM orders 
        GROUP  
           BY customer_id
     ) x 
  JOIN 
     ( SELECT MIN(cnt) min_cnt
            , MAX(cnt) max_cnt 
         FROM 
            ( SELECT customer_id
                   , COUNT(*) cnt 
                FROM orders 
               GROUP 
                  BY customer_id
            ) n
     ) y 
    ON y.min_cnt = x.cnt 
    OR y.max_cnt = x.cnt;

答案 1 :(得分:1)

我意识到,如果不多次调用相同的子查询,就无法在单个查询中运行它。当您引用min(numOrders)和max(numOrders)时,您必须将numOrders存储为时态表或计算两次。如果请求相同,DBMS很可能会缓存您的请求,因此您不必担心浪费资源。

所以你的查询必须有点重写并且足够好。我的变种是

select customer_id , count(order_id) as num 
from customers right outer join orders using(customer_id)
group by customer_id
having 
  num = (SELECT min(num) FROM (select count(order_id) as num 
    from customers right outer join orders using(customer_id)
    group by customer_id) numOrders)
or  
  num = (SELECT max(num) FROM (select count(order_id) as num 
    from customers right outer join orders using(customer_id)
    group by customer_id) numOrders)

您可以使用此sqlfiddle

进行检查

答案 2 :(得分:0)

如果我绝对觉得这必须是一个查询,我可能只使用union all

(
select
  customer_id,
  count(*) as num
from bab_customer right outer join bab_order_details using(customer_id)
group by customer_id
order by num desc limit 1
)
union all
(
select
  customer_id,
  count(*) as num
from bab_customer right outer join bab_order_details using(customer_id)
group by customer_id
order by num asc limit 1
)

最初,我一直认为这会因为避免连接中间值而表现更好。但是,我没有看到任何性能提升。 (如果它更快,那么限制可以提升到某个任意数字,并且应用程序可以减少一些额外的值而不会损失大部分增加的性能)

但是,没有骰子。