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 日之前的 1 月日期,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 天平均值很感兴趣。请注意,表中的日期是不规则的,因此我不能使用日期间隔;我需要表中的最后 20 条记录,而不仅仅是过去 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
子句的视图定义。有没有办法限制我的聚合选择中的数据而不诉诸子查询,以便解决这两个问题?
I have a table that looks something like this:
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 |
+------------+------------+------------+
I'm trying to create a view (call it AggregateView
) that will, for each date and for each data column, show a few different aggregates. For example, select * from AggregateView where Date = '2012-01-23'
might give:
+------------+--------------+----------------+--------------+----------------+
| Date | Data1_MTDAvg | Data1_20DayAvg | Data2_MTDAvg | Data2_20DayAvg |
+------------+--------------+----------------+--------------+----------------+
| 2012-01-23 | 697.71 | 566.34 | 601.37 | 192.13 |
+------------+--------------+----------------+--------------+----------------+
where Data1_MTDAvg
shows avg(DailyData1)
for each date in January prior to Jan 23, and Data1_20DayAvg
shows the same but for the prior 20 dates in the table. I'm no SQL ninja, but I was thinking that the best way to do this would be via subqueries. The MTD average is easy:
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;
But I'm getting hung up on the 20-day average due to the need to limit the number of results returned. Note that the dates in the table are irregular, so I can't use a date interval; I need the last twenty records in the table, rather than just all records over the last twenty days. The only solution I've found is to use a nested subquery to first limit the records selected, and then take the average.
Alone, the subquery works for individual hardcoded dates:
select avg(t2.DailyData1) Data1_20DayAvg
from (select DailyData1
from DataTable
where Date <= '2012-01-23'
order by Date desc
limit 0,20) t2;
But trying to embed this as part of the greater query blows up:
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 searching around I get the impression that you can't use correlated subqueries as part of a from
clause, which I think is where the problem is here. The other issue is that I'm not sure if MySQL will accept a view definition containing a from
clause in a subquery. Is there a way to limit the data in my aggregate selection without resorting to subqueries, in order to work around these two issues?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
不可以,您不能在
FROM
子句中使用关联子查询。但您可以在ON
条件中使用它们:类似,对于许多日期:
两个查询都假设
Datatable.Date
具有UNIQUE
约束。No, you can't use correalted subqueries in the
FROM
clause. But you can use them in theON
conditions:Similar, for many dates:
Both queries assume that
Datatable.Date
has aUNIQUE
constraint.