【问题标题】:group by query challenge按查询挑战分组
【发布时间】:2009-01-09 18:25:33
【问题描述】:

我有这些表:

customer
--------
customer_id int
name        varchar(255)

order
-----
order_id    int
customer_id int
discount    boolean

我可以通过如下查询获得每个客户的订单数量:

select c.id, count(o.order_id)
from customer c 
left join order as o using c.customer_id = o.customer_id
group by 1

或者,我可以通过以下方式获取每个客户的折扣订单数量:

select c.id, count(o.order_id)
from customer c 
left join order as o using c.customer_id = o.customer_id and o.discount = true
group by 1

但我想不出在一个查询中同时获取两者的方法。我尝试了以下方法:

select c.id, count(o.order_id), count(o2.order_id)
from customer c 
left join order as o using c.customer_id = o.customer_id
left join order as o2 using c.customer_id = o2.customer_id and o2.discount = true
group by 1

但它没有用。是否可以在单个(MySql)查询中计算两者?

干杯, 唐

【问题讨论】:

    标签: sql mysql


    【解决方案1】:

    怎么样

    select c.id, count(o.order_id),sum(if(o.discount,1,0))
    from customer c 
    left join order as o using c.customer_id = o.customer_id
    group by c.id
    

    【讨论】:

    • 在没有 IF 函数的系统中,可以使用 CASE 表达式或 DECODE 函数。
    • 你说得对,CASE是比较标准的SQL,但是OP说他用的是MySQL,支持IF()函数。
    【解决方案2】:

    你可以做类似的事情

    select 
     c.id,
     sum(case o.discount when true then 1 else 0 end) as 'total discounted',
     count(o.order_id) as 'total orders'
    from customer as c
     left join order as o using c.customer_id = o.customer_id 
    group by c.id
    

    【讨论】:

      【解决方案3】:

      其他答案很接近,但我是这样写的:

      SELECT c.id, COUNT(o.order_id) AS order_count, 
        SUM(o.discount = true) AS discount_order_count
      FROM customer c 
        LEFT OUTER JOIN order AS o USING (customer_id)
      GROUP BY c.id;
      

      注意USING 的用法需要括号,并且它只接受将与= 进行比较的列列表。 USING 语法不能像 ON 语法那样给出完整的比较表达式。

      您还可以简化 SUM() 中的表达式,因为相等比较返回 1 或 0。

      另见“Query: count multiple aggregates per item

      【讨论】: