2012-01-30 135 views
3

限制彙總數據時替代嵌套子查詢我有一個表,看起來是這樣的:MySQL的 - 在相關子查詢

DataTable 
+------------+------------+------------+ 
| Date  | DailyData1 | DailyData2 | 
+------------+------------+------------+ 
| 2012-01-23 |  146.30 |  212.45 | 
| 2012-01-20 |  554.62 |  539.11 | 
| 2012-01-19 |  710.69 |  536.35 | 
+------------+------------+------------+ 

我試圖創建一個視圖(稱之爲AggregateView)即會,爲每個日期和每個數據列顯示幾個不同的聚合。例如,select * from AggregateView where Date = '2012-01-23'可能會給:

+------------+--------------+----------------+--------------+----------------+ 
| Date  | Data1_MTDAvg | Data1_20DayAvg | Data2_MTDAvg | Data2_20DayAvg | 
+------------+--------------+----------------+--------------+----------------+ 
| 2012-01-23 |  697.71 |   566.34 |  601.37 |   192.13 | 
+------------+--------------+----------------+--------------+----------------+ 

其中Data1_MTDAvg顯示avg(DailyData1)在一月之前,1月23日,和Data1_20DayAvg每個日期顯示相同,但​​在表中的前20日。我不是SQL忍者,但我一直在想,最好的辦法是通過子查詢。該MTD平均很簡單:

select t1.Date, (select avg(t2.DailyData1) 
       from DataTable t2 
       where t2.Date <= t1.Date 
        and month(t2.Date) = month(t1.Date) 
        and year(t2.Date) = year(t1.Date)) Data1_MTDAvg 
from DataTable t1; 

,但我發現掛了20日均線,由於需要限制的結果數返回。請注意,表中的日期不規則,所以我不能使用日期間隔;我需要表格中的最後二十條記錄,而不是過去二十天中的所有記錄。我發現的唯一解決方案是使用嵌套子查詢來首先限制所選記錄,然後取平均值。

僅此一項,子查詢適用於單個硬編碼日期:

select avg(t2.DailyData1) Data1_20DayAvg 
from (select DailyData1 
     from DataTable 
     where Date <= '2012-01-23' 
     order by Date desc 
     limit 0,20) t2; 

但試圖嵌入這個作爲更大查詢的一部分炸燬:

select t1.Date, (select avg(t2.DailyData1) Data1_20DayAvg 
       from (select DailyData1 
         from DataTable 
         where Date <= t1.Date 
         order by Date desc 
         limit 0,20) t2) 
from DataTable t1; 
ERROR 1054 (42S22): Unknown column 't1.Date' in 'where clause' 

大約從搜索,我得到的印象是,您不能使用相關子查詢作爲from子句的一部分,我認爲這是問題出在哪裏。另一個問題是,我不確定MySQL是否會接受在子查詢中包含from子句的視圖定義。爲了解決這兩個問題,是否有辦法限制我的總體選擇中的數據而不訴諸子查詢?

回答

1

不,您不能在FROM子句中使用correalted子查詢。但是你可以在ON條件下使用:

SELECT AVG(d.DailyData1) Data1_20DayAvg 
     --- other aggregate stuff on d (Datatable) 
FROM 
     (SELECT '2012-01-23' AS DateChecked 
    ) AS dd 
    JOIN 
     DataTable AS d 
    ON 
     d.Date <= dd.DateChecked 
    AND 
     d.Date >= COALESCE( 
     (SELECT DailyData1 
     FROM DataTable AS last20 
     WHERE Date <= dd.DateChecked 
      AND (other conditions for last20) 
     ORDER BY Date DESC 
     LIMIT 1 OFFSET 19 
    ), '1001-01-01' ) 
WHERE (other conditions for d Datatable) 

類似,許多日期:

SELECT dd.DateChecked 
    , AVG(d.DailyData1) Data1_20DayAvg 
     --- other aggregate stuff on d (Datatable) 
FROM 
     (SELECT DISTINCT Date AS DateChecked 
     FROM DataTable 
    ) AS dd 
    JOIN 
     DataTable AS d 
    ON 
     d.Date <= dd.DateChecked 
    AND 
     d.Date >= COALESCE( 
     (SELECT DailyData1 
     FROM DataTable AS last20 
     WHERE Date <= dd.DateChecked 
      AND (other conditions for last20) 
     ORDER BY Date DESC 
     LIMIT 1 OFFSET 19 
    ), '1001-01-01' ) 
WHERE (other conditions for d Datatable) 
GROUP BY 
     dd.DateChecked 

兩個查詢假設Datatable.DateUNIQUE約束。