我有一个具有以下结构的mysql表
| Field | Type |
+----------------+--------------+
| Data | timestamp |
| ticker | varchar(250) |
| sentiment | double |
| numberofTweets | int(11) |
有70种不同的代码,我需要计算每种代号的加权平均值。
我正在做以下事情:
select ticker, round(sum(sentiment)/sum(numberofTweets),2) as wAverage
from sentiment
WHERE ticker = 'GBP/USD'
order by data desc
limit 288;
在单个查询中是否有办法处理所有代码?
提前Tks!
编辑1:
我需要为每个自动收报机使用288条记录进行计算,因此使用GROUP BY clausule将无效!
答案 0 :(得分:1)
为了简化您的问题,我使用下表:
CREATE TABLE `items` (
`id` MEDIUMINT(8) UNSIGNED NOT NULL,
`group_id` TINYINT(3) UNSIGNED NOT NULL,
`val` DOUBLE UNSIGNED NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
INDEX `group_id` (`group_id`)
) ENGINE=InnoDB;
测试数据包含100个组,每组平均1000个项目(总共100K行)。
set @num_rows = 100000;
set @per_group = 1000;
set @num_groups = @num_rows div @per_group;
insert into items (id, group_id, val)
select seq as id
, floor(rand(1)*@num_groups) + 1 as group_id
, rand(2) as val
from seq_1_to_1000000
where seq <= @num_rows
;
任务:每val
获取最新288行group_id
的总和。
不需要每组288行,它只是
select group_id, sum(val)
from items
group by group_id
但首先,您需要将数据集限制为每组288行。每组搜索&#34; mysql top n&#34;你会在SO上找到很多相关的问题。
大多数答案都会使用会话变量:
select group_id, sum(val)
from (
select i.group_id, i.val,
case when i.group_id = @group
then @rn:=@rn+1
else @rn:=1
end rn,
@group := i.group_id
from items i
cross join (select @rn := null, @group := null) init_vars
order by i.group_id, i.id desc
) t
where rn <= 288
group by group_id
order by group_id
查询时间:62 - 78 ms(我的客户没有显示确切的数字)。但是 - 使用此解决方案,您依赖于引擎的执行顺序,这可能会在将来的版本中发生变化。
其他一些答案使用selfjoin:
select group_id, sum(val)
from (
select i.group_id, i.val
from items i
join items i1
on i1.group_id = i.group_id
and i1.id >= i.id
group by i.id
having count(*) <= 288
) t
group by group_id
order by group_id
但性能仅适用于小组(平均组大小<= 10)。查询时间:17秒
还有一个&#34;技巧&#34;使用SUBSTRING_INDEX(GROUP_CONCAT(...), ...)
,可能需要为大型群组调整@@group_concat_max_len
。
但我更喜欢这个:
select i.group_id, sum(i.val)
from items i
where i.id >= coalesce((
select i1.id
from items i1
where i1.group_id = i.group_id
order by i1.id desc
limit 1
offset 287
), 0)
group by i.group_id
order by i.group_id
它首先在相关子查询中找到每组第288个最高的id,并且仅使用具有更高或相等ID的行。如果组的行少于288行,则将使用所有行(id> = 0)。 查询时间:78 - 94 ms。
根据您的问题进行调整,您将获得:
select s.ticker, round(sum(sentiment)/sum(numberofTweets),2) as wAverage
from sentiment s
where s.data >= coalesce((
select s1.data
from sentiment s1
where s1.ticker = s.ticker
order by s1.data desc
limit 1
offset 287
), from_unixtime(0))
group by s.ticker
order by s.ticker
请注意,如果按非唯一列对结果进行排序,则无法很好地定义限制结果集。因此,如果两个时间段相等,它可能会使用289行或更多行。使用AUTO_INCREMENT PRIMARY KEY更好。