У меня есть таблица, которая выглядит примерно так:
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)
для каждой даты в январе до 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
в подзапросе. Есть ли способ ограничить данные в моем совокупном выборе, не прибегая к подзапросам, чтобы обойти эти две проблемы?