2014-10-27 62 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