to my_web 因为记录删除后,会有空的留下,ID,数目有限制,到最大值后,会从已删除的结点中选一个来使用
create table lk7( id int not null auto_increment primary key, num int ) engine = myisam;insert into lk7(num) values (1),(2),(4),(6),(10), (3),(5),(7),(8),(9);create temporary table tmp select num from lk7 order by num asc; select * from tmp; query result(10 records) num 1 2 3 4 5 6 7 8 9 10
to yueliangdao0608 我晕了,我是数据库里已有 1),(2),(4),(6),(10),当然这个值是为固定的,只是举个例子而已 我想得到 {3),(5),(7),(8),(9);这组数据是预先不可知的 根据已有的记录可以判断出来的 用一个循环当然是可以取出数据的 我想问的是有没有简单的方法
假设原来的表示a,建立一个1-max(id)的临时表,这个id肯定是连续的,这个表为b,然后a和b连接,select b.id from a,b where a.id!=b.id;这个查出来就是楼主想要的那些。 是不是这个意思了
set @kid=1; select id,body,@kid:=@kid+1 as kid from a where id < @kid+1 order by kid desc limit 1;
测试数据是这样的 a表 id,body 两字段. 30w数据量 删除了id为 295010和295027 的数据 以下为查询语句及其结果. 第一句查询到删除条的前一数据. 如果你比较懒可以直接使用第二条拿到已删除编号. 这种方法只能取出最小的被删除编号. 同样也可以重新构造取出最大的被删除编号.mysql> set @kid=1; select id,body,@kid:=@kid+1 as kid from a where id < @kid+1 order by kid desc limit 1; Query OK, 0 rows affected+--------+------+--------+ | id | body | kid | +--------+------+--------+ | 295009 | abbs | 295010 | +--------+------+--------+ 1 row in setmysql> set @kid=1; select id+1,@kid:=@kid+1 as kid from a where id < @kid+1 order by kid desc limit 1; Query OK, 0 rows affected+--------+--------+ | id+1 | kid | +--------+--------+ | 295010 | 295010 | +--------+--------+ 1 row in set
忘了最后要回答你的问题了. 得到这个编号(295010)后 插入时编号就写 295010. 然后再取最小已删除编号,插入,补全就可以. 问题的关键在于找到已被删除的编号有哪些.insert a (id,body) values(295010,'test'); Query OK, 1 row affected set @kid=1; select id+1,@kid:=@kid+1 as kid from a where id < @kid+1 order by kid desc limit 1; Query OK, 0 rows affected+--------+--------+ | id+1 | kid | +--------+--------+ | 295027 | 295027 | +--------+--------+ 1 row in set
to SysTem128 mysql> set @a = 1; -> select c+1,@a:=@a+1 as t from c where c<@a+1 order by c desc limit 1; -> // Query OK, 0 rows affected (0.00 sec)+-----+------+ | c+1 | t | +-----+------+ | 2 | 2 | +-----+------+ 1 row in set (0.00 sec)你那个语句不对吧,MYSQL 查出来明显是2,
to ideal_1983 你的想法倒是可行的,如果实在没办法就用你的一试
set @kid=1; select id,body,@kid:=@kid+1 as kid from a where id < @kid+1 order by kid desc limit 1; 这很明显是放在一起的语句,不是两条不相干的语句.@kid需要初始化为1. 这么精良的语句,大量的测试数据,都证明它是正确的.你竟然由于自己的低级错误否定了它,可悲.
因为兴趣关系,SysTem128的语句我也测试过,可用~~~~
请看一下,下面的测试有何问题,按SYSTEM128程序,应该得出是8,而事实上,我确实得出的是2,难道是因为MYSQL 版本的问题? mysql> delimiter // mysql> select * from c;// +----+ | c | +----+ | 1 | | 2 | | 4 | | 3 | | 5 | | 6 | | 10 | | 7 | | 9 | +----+ 9 rows in set (0.00 sec)mysql> set @a = 1; -> select c,@a:=@a+1 from c where c<@a+1 order by c desc limit 1; -> // Query OK, 0 rows affected (0.00 sec)+---+----------+ | c | @a:=@a+1 | +---+----------+ | 1 | 2 | +---+----------+ 1 row in set (0.01 sec)mysql>
mysql>set @a=1; 你这样执行,请问这条语句有什么用处?你这里点完回车,下面这句和这个就一点关系都没有了. ->select c,@a:=@a+1 from c where c <@a+1 order by c desc limit 1; ->//
我日了,还不对,郁闷,老大,你们什么版本的MYSQL mysql> select * from c; -> // +-----+ | c_f | +-----+ | 1 | | 2 | | 4 | | 3 | | 5 | | 6 | | 10 | | 7 | | 9 | +-----+ 9 rows in set (0.00 sec)mysql> set @a = 1; select c_f,@a:=@a+1 as tmp_id from c where c_f<@a+1 order by tmp_id desc limit 1; -> // Query OK, 0 rows affected (0.00 sec)+-----+--------+ | c_f | tmp_id | +-----+--------+ | 3 | 4 | +-----+--------+ 1 row in set (0.01 sec)mysql>
哦~你需要对id字段也进行排序. 看来你不知道这个语句是怎么运作的. id 字段是自增的 或者说是自然排序的 @kid 也就构造出一个自然数序列,和记录数同步递增. 而你的id字段是混序的,所以会取出不和序列的3.
mysql> set @a = 1; select c_f,@a:=@a+1 as tmp_id from (select c_f from c order b y c_f asc) as c1 where c_f<@a+1 order by tmp_id desc limit 1;// Query OK, 0 rows affected (0.00 sec)+-----+--------+ | c_f | tmp_id | +-----+--------+ | 7 | 8 | +-----+--------+ 1 row in set (0.01 sec)我晕,这样才行,郁闷 结分了
因为记录删除后,会有空的留下,ID,数目有限制,到最大值后,会从已删除的结点中选一个来使用
create table lk7(
id int not null auto_increment primary key,
num int
) engine = myisam;insert into lk7(num) values
(1),(2),(4),(6),(10),
(3),(5),(7),(8),(9);create temporary table tmp select num from lk7 order by num asc;
select * from tmp;
query result(10 records)
num
1
2
3
4
5
6
7
8
9
10
我晕了,我是数据库里已有 1),(2),(4),(6),(10),当然这个值是为固定的,只是举个例子而已
我想得到 {3),(5),(7),(8),(9);这组数据是预先不可知的 根据已有的记录可以判断出来的
用一个循环当然是可以取出数据的
我想问的是有没有简单的方法
是不是这个意思了
set @kid=1; select id,body,@kid:=@kid+1 as kid from a where id < @kid+1 order by kid desc limit 1;
a表 id,body 两字段.
30w数据量
删除了id为 295010和295027 的数据
以下为查询语句及其结果.
第一句查询到删除条的前一数据.
如果你比较懒可以直接使用第二条拿到已删除编号.
这种方法只能取出最小的被删除编号.
同样也可以重新构造取出最大的被删除编号.mysql> set @kid=1; select id,body,@kid:=@kid+1 as kid from a where id < @kid+1 order by kid desc limit 1;
Query OK, 0 rows affected+--------+------+--------+
| id | body | kid |
+--------+------+--------+
| 295009 | abbs | 295010 |
+--------+------+--------+
1 row in setmysql> set @kid=1; select id+1,@kid:=@kid+1 as kid from a where id < @kid+1 order by kid desc limit 1;
Query OK, 0 rows affected+--------+--------+
| id+1 | kid |
+--------+--------+
| 295010 | 295010 |
+--------+--------+
1 row in set
得到这个编号(295010)后
插入时编号就写 295010.
然后再取最小已删除编号,插入,补全就可以.
问题的关键在于找到已被删除的编号有哪些.insert a (id,body) values(295010,'test');
Query OK, 1 row affected
set @kid=1; select id+1,@kid:=@kid+1 as kid from a where id < @kid+1 order by kid desc limit 1;
Query OK, 0 rows affected+--------+--------+
| id+1 | kid |
+--------+--------+
| 295027 | 295027 |
+--------+--------+
1 row in set
则不能补
要补的话必须将auto_increment去掉
这样应可以补了
查找ID的号,排序,看哪些ID为空
看MYSQL里的插入记录是否可以插在某记录前如不能,只有别建新表,倒入,没有记当的ID行暂为空,其他的ID相同时导入
1,MySQL auto_increment 字段可以补,指定空id直接插入即可.
2,本帖的问题就在于找'ID为空'的地方,所以你是在问还是在答?总结,看帖需要看回帖,回帖需要认真负责.
===================================================================
在插入之前,如何找到3作为插入数据的id,是问题的关键,也就是找到第一个id连续的断开点。
建议:加一字段(breakpoint)保存断点标志,默认为null,做删除操作时自动将上一条记录的breakpoint设为1,则插入的id为breakpoint为1的id再加1,更新breakpoint记录,如何数据量大则加一字段未免浪费,可以考虑用文件记录breakpoint的id.如何已经设计成型,现在想补全,问题就是每次插入时如何找到第一个id连续的断开点。
接受批评,也期等你的好办法和好思路
结果如下:
1、在id 为auto_increment 的情况下,如果id不存在,可以直接插入
2、如果id 已存在,插入出错可以做个临时表循环插入,在PHP中操作,如果没有出错,说明这个ID是要补的,记入数组。如查出错,继续循环下一个数!补插时根据数据组中的值直接插入!
我代码功底不好,大侠给写一个吧!
mysql> set @a = 1;
-> select c+1,@a:=@a+1 as t from c where c<@a+1 order by c desc limit 1;
-> //
Query OK, 0 rows affected (0.00 sec)+-----+------+
| c+1 | t |
+-----+------+
| 2 | 2 |
+-----+------+
1 row in set (0.00 sec)你那个语句不对吧,MYSQL 查出来明显是2,
你的想法倒是可行的,如果实在没办法就用你的一试
mysql> delimiter //
mysql> select * from c;//
+----+
| c |
+----+
| 1 |
| 2 |
| 4 |
| 3 |
| 5 |
| 6 |
| 10 |
| 7 |
| 9 |
+----+
9 rows in set (0.00 sec)mysql> set @a = 1;
-> select c,@a:=@a+1 from c where c<@a+1 order by c desc limit 1;
-> //
Query OK, 0 rows affected (0.00 sec)+---+----------+
| c | @a:=@a+1 |
+---+----------+
| 1 | 2 |
+---+----------+
1 row in set (0.01 sec)mysql>
mysql>set @a=1; 你这样执行,请问这条语句有什么用处?你这里点完回车,下面这句和这个就一点关系都没有了.
->select c,@a:=@a+1 from c where c <@a+1 order by c desc limit 1;
->//
然后再回去SELECT @a看看,绝对是100
而且,我按你的写法,放在一行,结果一样
mysql> select * from c;
-> //
+-----+
| c_f |
+-----+
| 1 |
| 2 |
| 4 |
| 3 |
| 5 |
| 6 |
| 10 |
| 7 |
| 9 |
+-----+
9 rows in set (0.00 sec)mysql> set @a = 1; select c_f,@a:=@a+1 as tmp_id from c where c_f<@a+1 order by
tmp_id desc limit 1;
-> //
Query OK, 0 rows affected (0.00 sec)+-----+--------+
| c_f | tmp_id |
+-----+--------+
| 3 | 4 |
+-----+--------+
1 row in set (0.01 sec)mysql>
看来你不知道这个语句是怎么运作的.
id 字段是自增的 或者说是自然排序的
@kid 也就构造出一个自然数序列,和记录数同步递增.
而你的id字段是混序的,所以会取出不和序列的3.
mysql> set @a = 1; select c_f,@a:=@a+1 as tmp_id from (select c_f from c order b
y c_f asc) as c1 where c_f<@a+1 order by tmp_id desc limit 1;//
Query OK, 0 rows affected (0.00 sec)+-----+--------+
| c_f | tmp_id |
+-----+--------+
| 7 | 8 |
+-----+--------+
1 row in set (0.01 sec)我晕,这样才行,郁闷
结分了
插入新数据后,虽然ID是一样的,但由于存储位置已改变,所以肯定是乱序