感谢楼上的回复!!!这是一个访客日志表, 这个表的记录虽然多,但是,结构却非常简单(注:无关的字段省略了):create table visitlog ( guestid varchar(20) not null, date1900 int not null, visitid int null, primary key (guestid) );以前没有visitid, 后来新加了visitid字段, 要求把每个客人的访问记录,按时间排序后进行编号:希望的结果如下: 张三 970101 1 张三 970201 2 张三 980102 3 李四 950101 1 李四 960304 2 李四 980102 3 李四 1020101 4 .....数据库是 ubuntu 10.04 官方源上的 mysql server 版本是: 5.1.41 - 3 ubuntu 12.3
update visitlog c inner join (select a.guestid,count(b.guestid) as ma from visitlog a left join visitlog b on a.guestid=b.guestid and a.date1900>=b.date1900 group by a.guestid) d on c.guestid=d.guestid set c.visitid=d.ma
按照你的提示, 我写了一个存储过程(如下),是否还可以改进呢??? 再次感谢!!!--------------------------- (考虑到date1900已经是KEY的一部分,所以,order by就省了) create procedure CalcVID () begin declare done int default 0; declare AGeustID varchar(20); declare cursGeustID CURSOR FOR SELECT distinct guestid FROM visitlog;
declare CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1;
OPEN cursGeustID; repeat
FETCH cursGeustID INTO AGeustID; if not done then
update visitlog d, (select @RowID := 0) t set d.visitid = (@RowID := @RowID+1) where (d.guestid = AGeustID)
end if;
until done end repeat; CLOSE cursGeustID;
end;
没测试你的代码,从功能上应该是不错。 但从效率上来科,和上面的SQL语句没什么差别。用存储过程的目的就是想减少 表的JOIN。直接一个游标 select * from visitlog order by guestid,date1900 然后循环这个CURSOR, 用一个计数器来更新。这样,时间复杂度只是 O
set a.sno=b.k
建议你列出你的表结构,并提供测试数据以及基于这些测试数据的所对应正确结果。
参考一下这个贴子的提问方式http://topic.csdn.net/u/20091130/20/8343ee6a-417c-4c2d-9415-fa46604a00cf.html
1. 你的 create table xxx .. 语句
2. 你的 insert into xxx ... 语句
3. 结果是什么样,(并给以简单的算法描述)
4. 你用的数据库名称和版本(经常有人在MS SQL server版问 MySQL)
这样想帮你的人可以直接搭建和你相同的环境,并在给出方案前进行测试,避免文字描述理解上的误差。
(
guestid varchar(20) not null,
date1900 int not null,
visitid int null,
primary key (guestid)
);以前没有visitid, 后来新加了visitid字段, 要求把每个客人的访问记录,按时间排序后进行编号:希望的结果如下:
张三 970101 1
张三 970201 2
张三 980102 3
李四 950101 1
李四 960304 2
李四 980102 3
李四 1020101 4
.....数据库是 ubuntu 10.04 官方源上的 mysql server 版本是: 5.1.41 - 3 ubuntu 12.3
(select a.guestid,count(b.guestid) as ma from visitlog a left join visitlog b
on a.guestid=b.guestid and a.date1900>=b.date1900 group by a.guestid) d
on c.guestid=d.guestid
set c.visitid=d.ma
更正一下:
primary key (guestid, date1900)3楼的说明,因权限不够, 改不了, 请大家原谅....
+---------+----------+---------+
| guestid | date1900 | visitid |
+---------+----------+---------+
| 张三 | 970101 | NULL |
| 张三 | 970201 | NULL |
| 张三 | 980102 | NULL |
| 李四 | 950101 | NULL |
| 李四 | 960304 | NULL |
| 李四 | 980102 | NULL |
| 李四 | 1020101 | NULL |
+---------+----------+---------+
7 rows in set (0.03 sec)mysql> update visitlog a inner join (
-> select @x:=if(@v=guestid,@x+1,1) as vid ,guestid,date1900,@v:=guestid
-> from visitlog
-> order by guestid,date1900
-> ) b on a.guestid=b.guestid and a.date1900=b.date1900
-> set visitid=vid;
Query OK, 7 rows affected (0.05 sec)
Rows matched: 7 Changed: 7 Warnings: 0mysql> select * from visitlog;
+---------+----------+---------+
| guestid | date1900 | visitid |
+---------+----------+---------+
| 张三 | 970101 | 1 |
| 张三 | 970201 | 2 |
| 张三 | 980102 | 3 |
| 李四 | 950101 | 1 |
| 李四 | 960304 | 2 |
| 李四 | 980102 | 3 |
| 李四 | 1020101 | 4 |
+---------+----------+---------+
7 rows in set (0.00 sec)mysql>
按照你的提示, 我写了一个存储过程(如下),是否还可以改进呢???
再次感谢!!!---------------------------
(考虑到date1900已经是KEY的一部分,所以,order by就省了)
create procedure CalcVID ()
begin declare done int default 0; declare AGeustID varchar(20); declare cursGeustID CURSOR FOR
SELECT distinct guestid
FROM visitlog;
declare CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1;
OPEN cursGeustID; repeat
FETCH cursGeustID INTO AGeustID; if not done then
update visitlog d, (select @RowID := 0) t
set d.visitid = (@RowID := @RowID+1)
where (d.guestid = AGeustID)
end if;
until done end repeat; CLOSE cursGeustID;
end;
但从效率上来科,和上面的SQL语句没什么差别。用存储过程的目的就是想减少 表的JOIN。直接一个游标 select * from visitlog order by guestid,date1900
然后循环这个CURSOR, 用一个计数器来更新。这样,时间复杂度只是 O
mysql手册(http://mysql.tonnikala.org/doc/refman/5.1/en/cursors.html)上说, mysql的cursor是只读的,如果要修改记录,是否只能用独立的update语句? 如果是这样的话,是不是每次update都需要重新定位要被修改的那条记录,这样一来,效率是否会受影响呢?
是的 如果是这样的话,是不是每次update都需要重新定位要被修改的那条记录,这样一来,效率是否会受影响呢?
由于你的两个字段是主键,所以会使用索引,索引的索引很快,可以认为是常数。