按指定数量的有序行进行分组

发布于 2024-11-29 14:05:47 字数 895 浏览 1 评论 0原文

我的 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 - 这是产品 ID
price - 这是指定日期产品的价格

我想计算产品fid=1的平均价格。我想计算指定 fid 的前 n=3 行按日期排序的平均价格,然后计算按日期排序的另外 3 行的平均价格。

如何对前 3 行进行分组并计算平均值,然后对接下来的 3 行进行分组并计算平均值。在计算之前,我需要按日期对行进行排序,然后对 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

How can I create SQL Query to do suchcalculate?

提前致谢。

I have such table in my MySQL database:

---------------------------
|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 - this is the product id
price - this is the price of the product in specified day

I want to calculate average price of the product fid=1. I want to calculate the average price of first n=3 rows ordered by date for specified fid, and then calculate average price for another 3 rows ordered by date.

How can I group first 3 rows and calculate avg and then group next 3 rows and calculate avg. Before calculation I need to sort the rows by date and then group n rows.

If n=3 this should return such result:

--------------
|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

How can I create SQL Query to do such calculations?

Thanks in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

往日情怀 2024-12-06 14:05:47

不幸的是,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)

Unluckily mysql doesn't offer analytic functions like oracle,mssql and postgres do. So you have to play with variables to reach your goal.

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)
慈悲佛祖 2024-12-06 14:05:47

也许你可以使用

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

= 转换为秒,除以 3 天的秒,然后向下舍入

maybe you could use

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

= convert to secounds, divide by secounds for 3 days, and round down

ゃ人海孤独症 2024-12-06 14:05:47
SELECT AVG( price ) FROM my_table
    GROUP BY ( date - ( SELECT MIN( date ) FROM my_table WHERE fid = 1 ) ) DIV 3
    WHERE fid = 1
SELECT AVG( price ) FROM my_table
    GROUP BY ( date - ( SELECT MIN( date ) FROM my_table WHERE fid = 1 ) ) DIV 3
    WHERE fid = 1
入怼 2024-12-06 14:05:47
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
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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文