朋友问的一个问题:
已知表结构如下,要求得到股价连续上涨的天数:
mysql@localhost.test>select d,price from stock order by d;
+————+——-+
| d | price |
+————+——-+
| 2012-05-01 | 20 |
| 2012-05-02 | 23 |
| 2012-05-03 | 25 |
| 2012-05-04 | 28 |
| 2012-05-05 | 30 |
| 2012-05-06 | 31 |
| 2012-05-07 | 33 |
| 2012-05-08 | 31 |
| 2012-05-09 | 39 |
| 2012-05-10 | 33 |
| 2012-05-11 | 40 |
| 2012-05-12 | 42 |
+————+——-+
结果应该如下(第一天不参与统计):
+————+——-+——+
| d | price | n |
+————+——-+——+
| 2012-05-02 | 23 | 1 |
| 2012-05-03 | 25 | 2 |
| 2012-05-04 | 28 | 3 |
| 2012-05-05 | 30 | 4 |
| 2012-05-06 | 31 | 5 |
| 2012-05-07 | 33 | 6 |
| 2012-05-08 | 31 | 0 |
| 2012-05-09 | 39 | 1 |
| 2012-05-10 | 33 | 0 |
| 2012-05-11 | 40 | 1 |
| 2012-05-12 | 42 | 2 |
+————+——-+——+
查询语句如下:
select d,price,@a:=if(zf=1,@a+zf,0) n from (select a.d,a.price,if(a.price-b.price>0,1,0) zf from stock a,stock b where a.d=date_add(b.d,interval 1 day) order by d) t,(select @a:=0) as a ;
思路是,先用自连接计算出当天和上一天的股票差值,如果>0,取值1,否则取值0
然后用子查询,用@a变量计算累计值,但如果是0就不计算。
该语句的问题是即使d上建了索引,因为有a.d=date_add(b.d,interval 1 day)语句,查询效率不高
explain select d,price,@a:=if(zf=1,@a+zf,0) n from (select a.d,a.price,if(a.price-b.price>0,1,0) zf from stock a,stock b where a.d=date_add(b.d,interval 1 day) order by d) t,(select @a:=0) as a ;
+—-+————-+————+——–+—————+——+———+——+——+———————————+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+—-+————-+————+——–+—————+——+———+——+——+———————————+
| 1 | PRIMARY |
| 1 | PRIMARY |
| 3 | DERIVED | NULL | NULL | NULL | NULL | NULL | NULL | NULL | No tables used |
| 2 | DERIVED | b | ALL | NULL | NULL | NULL | NULL | 12 | Using temporary; Using filesort |
| 2 | DERIVED | a | ALL | idx_d | NULL | NULL | NULL | 12 | Using where; Using join buffer |
+—-+————-+————+——–+—————+——+———+——+——+———————————+
所以可以增加一个pre列,存放上一天的价格,用以下语句更新:
update stock a,stock b set a.pre=b.price where a.d=date_add(b.d,interval 1 day);
MSSQL:update a set a.pre=b.price from stock a,stock b where …;
查询语句变为
select d,price,@a:=if(zf=1,@a+zf,0) n from (select a.d,a.price,if(a.price-a.pre>0,1,0) zf from stock a order by d) t,(select @a:=0) as a ;
没有连接,更为高效,以后只需要更新新增数据的pre字段即可

踩踩