MySQL - 导致性能问题的多个子查询

时间:2017-05-22 16:54:12

标签: mysql tsql

我试图通过我试图展示的MySql查询将一些数据拉到一起;

AgentName, 
AgentGroupCode,
YearToDateRevenue, 
7DayRevenue, 
YTDOrderCount, 
7DayOrderCount.

就目前而言,我现在使用多个子查询来提取YTD和7天的细节,这对系统造成了巨大的压力 - 它需要大约130秒才能完成,这在我眼里是不可接受的。

我想知道是否有一种更为流畅的方式来制作它?我目前的代码如下:

SET @YTDStart = '2017-01-01';
Set @YTDEnd = '2017-05-07';


SELECT b.AgentRef, a.Name, a.AgentGroup,
(
  SELECT sum(b.basicprice) from bookings b WHERE b.bookingdate BETWEEN @YTDStart AND @YTDEnd
) as YTDRevenue,

(
  SELECT sum(b.basicprice) from bookings b WHERE b.bookingdate BETWEEN @WeekStart AND @WeekEnd
) as 7DayRevenue
#Similar code for the Count but will exclude for this example.

FROM bookings b 
INNER JOIN Agent a ON b.agentref = a.code
GROUP BY b.agentref

3 个答案:

答案 0 :(得分:0)

确实不需要这种数据的子查询,而是可以使用条件聚合。

SELECT b.AgentRef, a.Name, a.AgentGroup
   , SUM(CASE WHEN b.bookingdate BETWEEN @YTDStart AND @YTDEnd THEN b.basicprice ELSE 0 END) AS YTDRevenue
   , SUM(CASE WHEN b.bookingdate BETWEEN @WeekStart AND @WeekEnd THEN b.basicprice ELSE 0 END) AS `7DayRevenue`
#Similar code for the Count but will exclude for this example.
FROM bookings b 
INNER JOIN Agent a ON b.agentref = a.code
WHERE /* assuming week date range within year date range, 
         and you only care about b.agentrefs that "occurred" in the time frame 
      */
b.bookingdate BETWEEN @YTDStart AND @YTDEnd
GROUP BY b.agentref
;

从技术上讲,如果我在WHERE中的评论是正确的,那么YTD汇总不需要是有条件的。

答案 1 :(得分:0)

您可以在聚合表上使用连接

SELECT b.AgentRef, a.Name, a.AgentGroup, t1.YTDRevenue, t2.7DayRevenue
FROM bookings b 
INNER JOIN Agent a ON b.agentref = a.code

INNER JOIN (
    SELECT b.AgentRef, sum(b.basicprice)  as YTDRevenue 
    from bookings b 
    WHERE b.bookingdate BETWEEN @YTDStart AND @YTDEnd
    GROUP BY b.agentref
) t1 on t1.AgentRef = b.agentref
INNER JOIN (
    SELECT b.AgentRef, sum(b.basicprice) as 7DayRevenue
    from bookings b 
    WHERE b.bookingdate BETWEEN @WeekStart AND @WeekEnd
    GROUP BY b.agentref
) t2 t2.AgentRef = b.agentref

答案 2 :(得分:0)

您可以尝试使用左连接而不是子选择。另外,请确保在ON和WHERE子句中使用的列上有索引。

SET @YTDStart = '2017-01-01';
SET @YTDEnd = '2017-05-07';
SET @WeekStart = '2017-05-01';
SET @WeekEnd = '2017-05-07';

SELECT 
    b.AgentRef, 
    a.Name, 
    a.AgentGroup,
    SUM(b.basicprice) as `YTDRevenue`,
    SUM(c.basicprice) as `7DayRevenue`,
    COUNT(b.basicprice) as `YTDCount`,
    COUNT(c.basicprice) as `7DayCount`
FROM Agent a
LEFT JOIN bookings b 
ON b.agentref = a.code AND b.bookingdate BETWEEN @YTDStart AND @YTDEnd
LEFT JOIN bookings c
ON b.agentref = a.code AND b.bookingdate BETWEEN @WeekStart AND @WeekEnd
GROUP BY b.agentref