2012-01-30 97 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约束。