我正在尝试显示客户列表以及他们所下订单的数量以及上次订单的日期。有些客户可能没有下订单。
我在注册日期过滤客户,目前我只对最近注册的客户感兴趣。我认为我当前的查询首先为所有客户运行子查询,然后执行WHERE查找。
如何提高此查询的效率?
select
customers.*,
addresses.*,
(select count(*) from orders where customerID=customers.customerID) orders,
(select orderDate from orders where customerID=customers.customerID order by orderID desc limit 1) lastOrder
from customers
left join addresses on customers.defaultCollection=addresses.addressID
where
registrationDate >= '2014-02-04'
答案 0 :(得分:2)
这是您的查询,每列都有表别名,以清楚地标识它们的来源(我希望我把它们弄好):
select c.*, a.*,
(select count(*)
from orders o
where o.customerID = c.customerID
) as orders,
(select o.orderDate
from orders o
where o.customerID = c.customerID
order by o.orderID desc
limit 1
) as lastOrder
from customers c left join
addresses a
on c.defaultCollection = a.addressID
where c.registrationDate >= '2014-02-04' ;
查询不一定是坏的。它可以从一些索引中受益:customers(registrationDate, defaultCollection, CustomerId)
,addresses(addressId)
,最重要的是orders(CustomerID, orderId, orderDate)
。这些索引可能足以达到您想要的性能。
实际上,将其转换为聚合查询可能没有用,因为您必须添加聚合:
select c.*, a.*, count(o.customerId) as numOrders,
substring_index(group_concat(o.OrderDate order by o.OrderId desc), ',', 1) as LastOrderIdOrderDate
from customers c left join
addresses a
on c.defaultCollection = a.addressID left join
orders o
on o.customerId = c.customerId
where c.registrationDate >= '2014-02-04'
group by c.customerId, a.AddressId;
substring_index()
表达式是您在问题中执行的操作 - 获取最大orderId
的日期。如果这是最大订单日期,那么更好的表达式是max(o.OrderDate)
。
答案 1 :(得分:0)
这有效吗?
select
c.*,
a.*,
count(*) ,
max(orderDate) as lastOrder
from customers c
left join addresses a
on c.defaultCollection=a.addressID
left join orders o
on o.customerID=c.customerID
where
registrationDate >= '2014-02-04'
group by o.customerID