Сгруппировать по указанным номерам упорядоченных строк - PullRequest
5 голосов
/ 11 августа 2011

В моей базе данных MySQL есть такая таблица:

---------------------------
|fid | price | date       |
---------------------------
|  1 | 1.23  | 2011-08-11 |
|  1 | 1.43  | 2011-08-12 |
|  1 | 1.54  | 2011-08-13 |
|  1 | 1.29  | 2011-08-14 |
|  1 | 1.60  | 2011-08-15 |
|  1 | 1.80  | 2011-08-16 |

fid - это идентификатор товара
price - это цена товара в указанный день

Хочу рассчитать среднюю цену товара fid=1.Я хочу рассчитать среднюю цену первых n=3 строк, упорядоченных по дате, для указанного fid, а затем вычислить среднюю цену для еще 3 строк, упорядоченных по дате.

Как сгруппировать первые 3 строки и рассчитатьavg, а затем сгруппировать следующие 3 строки и вычислить avg.Перед вычислением мне нужно отсортировать строки по дате, а затем сгруппировать n строк.

Если n=3, это должно вернуть такой результат:

--------------
|fid | price |
--------------
|  1 | 1.40  | 2011-08-11 -> 2011-08-13 - average price for 3 days
|  1 | 1.56  | 2011-08-14 -> 2011-08-16 - average price for 3 days

Как создать SQL-запрос дляделать такие расчеты?

Заранее спасибо.

Ответы [ 4 ]

2 голосов
/ 11 августа 2011

К сожалению, mysql не предлагает аналитических функций, таких как oracle, mssql и postgres.Таким образом, вы должны поиграть с переменными, чтобы достичь своей цели.

create table mytest (
id int not null auto_increment primary key,
fid int,
price decimal(4,2),
fdate date
) engine = myisam;

insert into mytest (fid,price,fdate)
values 
(1,1.23,'2011-08-11'),
(1,1.43,'2011-08-12'),
(1,1.54,'2011-08-13'),
(1,1.29,'2011-08-14'),
(1,1.60,'2011-08-15'),
(1,1.80,'2011-08-16');


select 
concat_ws('/',min(fdate),max(fdate)) as rng,
format(avg(price),2) as average from (
select *,@riga:=@riga+1 as riga
    from mytest,(select @riga:=0) as r order by fdate
     ) as t
group by ceil(riga/3);


+-----------------------+---------+
| rng                   | average |
+-----------------------+---------+
| 2011-08-11/2011-08-13 | 1.40    |
| 2011-08-14/2011-08-16 | 1.56    |
+-----------------------+---------+
2 rows in set (0.02 sec)
0 голосов
/ 11 августа 2011
SELECT AVG( price ) FROM my_table
    GROUP BY ( date - ( SELECT MIN( date ) FROM my_table WHERE fid = 1 ) ) DIV 3
    WHERE fid = 1
0 голосов
/ 11 августа 2011
select fid, avg(price), min(date), max(date)
from
    (select floor((@rownum := @rownum + 1)/3) as `rank`,  prices.*
    from prices, (SELECT @rownum:=-1) as r
    order by date) as t
group by rank
0 голосов
/ 11 августа 2011

возможно, вы могли бы использовать

GROUP BY FLOOR(UNIX_TIMESTAMP(date)/(60*60*24*3))

= конвертировать в секунды, делить на секунды в течение 3 дней и округлять вниз

...