【问题标题】:MySQL - alternatives to nested subqueries when limiting aggregate data in a correlated subqueryMySQL - 在相关子查询中限制聚合数据时替代嵌套子查询
【发布时间】:2012-01-30 18:23:13
【问题描述】:

我有一个看起来像这样的表:

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 显示 1 月 23 日之前的每个日期的 avg(DailyData1)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 子句的视图定义。为了解决这两个问题,有没有办法限制我的聚合选择中的数据而不诉诸子查询?

【问题讨论】:

    标签: mysql sql correlated-subquery


    【解决方案1】:

    不,您不能在 FROM 子句中使用关联子查询。但是您可以在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.Date 具有UNIQUE 约束。

    【讨论】:

      猜你喜欢
      • 2011-11-05
      • 2017-12-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-20
      相关资源
      最近更新 更多