我希望更新一些表的行,univ_members,以他们的宇宙#来区分它们的百分位数或等级。该pctile值在子查询中计算。子查询本身工作正常,但是当提供给更新时,“子查询返回多行”失败。代码块中的第23行是违规表达式。 (这段代码是从here (stackoverflow),here (a poster's blog)收集的,最终(我认为)来自一本书,“高性能MySQL”,Schwartz,Zaitsev,Tkachenko,p.648 et seq。第3版)
我无法让它与更新一起工作。我开始怀疑,在阅读了有关更新的30个不同帖子和“子查询返回多行”之后,这不是在一个复杂的查询中,MySQL是可能的,而我需要编写一个proc来通过循环来完成它。 可以在查询中在MySQL中完成,还是需要循环?如果有查询,该怎么做? 我想提一下,这个查询不使用自联接这一事实对我而言对性能非常有价值。我的生产表以112,000个记录开头,可能会增加到400万个。
第11行是计算pctile值的地方。第13行是初始化计数器变量的地方(显然只有一次)。内部选择命令由std_dev_rank(第15行)对每个pid的$ vol(美元 - 体积)的标准差进行排序,两者都是先前计算的。 @curr最初被设置为它们中的最高位置(第10行),然后是13,与前一个相比,因此给出了相应的排名。一些简单的算术随之而来。 我省略了你自己尝试的变量定义和其他细节,但我确实包含了univ_members表(第19行)。
如果您感兴趣,这超出了我的股票动量/价格估算和预测计划。 $ -volume是流动性的衡量标准。这是为了准备选择适合进一步检查的股票(pids)。 (每个'宇宙'都是跨时间的股票,经常重叠。这就是为什么表格可以超过现有股票的数量。)
1 create temporary table um like univ_members;
2 insert into um select * from univ_members where id_universe = @univ_num;
3
4 update um
5 set pctile =
6 (
7 select pctile from(
8 select
9 @prev := @curr,
10 @curr := std_dev_rank,
11 (100- ((@rank := IF(@prev= @curr, @rank, @rank+1))* @recs_per_pctile)) AS pctile
12 from univ_members
13 ,(select @curr := null, @prev := null, @rank := 0) x
14 where id_universe = @univ_num
15 order by std_dev_rank desc) q
16 where id_universe = @univ_num);
17
18 -- the univ_members table
19 create table univ_members
20 (
21 id_universe smallint(5) unsigned not null,
22 pid char(8) not null,
23 $vol double unsigned default null,
24 coef_cor double default null, -- 'distance' from median $vol
25 pctile double unsigned default null, -- another 'distance' measure
26 std_dev_rank double default null, -- individual std dev bracket
27
28 primary key pk_univ_members (id_universe, pid),
29 key k_$vol ($vol)
30 ) engine=InnoDB;
答案 0 :(得分:3)
您需要让子查询返回主键和百分位数。然后,您可以加入子查询并更新相应行中的列:
UPDATE um
JOIN (select id_universe, pid,
@prev := @curr,
@curr := std_dev_rank,
(100- ((@rank := IF(@prev= @curr, @rank, @rank+1))* @recs_per_pctile)) AS pctile
from univ_members
,(select @curr := null, @prev := null, @rank := 0) x
where id_universe = @univ_num
order by std_dev_rank desc) q
SET um.pctile = q.pctile
WHERE um.id_universe = q.id_universe AND um.pid = q.pid