2014-10-27 60 views
0

如何优化以下查询:如何优化下面使用三级select语句的查询?

我有两个表'calendar_table'和'consumption',在这里我使用这个查询来计算每年的每月消费。

日历表具有2005年至2009年的日,月和年,消费表已针对每月帐单周期收取消费数据。该查询将计算每个账单的天数,并使用该查找每个月的消耗。

SELECT id, 
     date_from as bill_start_date, 
     theYear as Year, 
     MONTHNAME(STR_TO_DATE(theMonth, '%m')) as month, 
     sum(DaysOnBill), 
     TotalDaysInTheMonth, 
     sum(perDayConsumption * DaysOnBill) as EstimatedConsumption 
    FROM 
    ( 
    SELECT 
     id, 
     date_from, 
     theYear, 
     theMonth, # use theMonth for displaying the month as a number 
     COUNT(*) AS DaysOnBill, 
     TotalDaysInTheMonth, 
     perDayConsumption 
    FROM 
     (
     SELECT 
      c.id, 
      c.date_from as date_from, 
      ct.dt, 
      y AS theYear, 
      month AS theMonth, 
      DAY(LAST_DAY(ct.dt)) as TotalDaysInTheMonth, 
      perDayConsumption 
     FROM 
      consumption AS c 
      INNER JOIN 
      calendar_table AS ct 
       ON ct.dt >= c.date_from 
        AND ct.dt<= c.date_to 
     ) AS allDates 
    GROUP BY 
     id, 
     date_from, 
     theYear, 
     theMonth) AS estimates 
GROUP BY 
     id, 
     theYear, 
     theMonth;  

大约需要1000秒才能完成大约100万条记录。可以做些什么来使其更快?

+0

在你的calendar_tables ...“dt”列是一个日期/时间?如果是这样,是不是所有的“时间”部分都是12:00:00(午夜/开始)? – DRapp 2014-10-27 16:53:42

+0

这只是一个日期 – 2014-10-27 17:02:32

回答

3

该查询有点怀疑,假装先做一个分组,然后再与另一个分组进行构建,实际上并非如此。

首先该法案加入所有的日子。然后我们按账单加上月份和年份进行分组,从而获得每月的数据。这可以一次完成,但查询首先加入,然后将结果作为派生表进行汇总。最后,再次获得结果并构建“另一个”组,其实与以前(账单加月和年)相同,并且完成了一些伪汇总(例如,总额(perDayConsumption * DaysOnBill),其与perDayConsumption相同* DaysOnBill,因为SUM在这里仅记录一条记录)。

这可以简单地写为:

SELECT 
    c.id, 
    c.date_from as bill_start_date, 
    ct.y AS Year, 
    MONTHNAME(STR_TO_DATE(ct.month, '%m')) as month, 
    COUNT(*) AS DaysOnBill, 
    DAY(LAST_DAY(ct.dt)) as TotalDaysInTheMonth, 
    SUM(c.perDayConsumption) as EstimatedConsumption 
FROM consumption AS c 
INNER JOIN calendar_table AS ct ON ct.dt BETWEEN c.date_from AND c.date_to 
GROUP BY 
    c.id, 
    ct.y, 
    ct.month; 

我不知道这是否会更快,或者MySQL的优化器不会通过查询看到自己和归结下来到这个进不去。

+0

呃,ct.month ??? – Strawberry 2014-10-27 17:23:15

+0

@Strawberry:那么,列y和月从消费或calendar_table中选择。我发现它更可能是calendar_table中的一个便利字段。 – 2014-10-27 17:25:43

+0

你在日历表中有一个名为month的列吗? – Strawberry 2014-10-27 17:28:38