Or another approach could be (using same example tables) mysql> set @a:=0; set @b:=0; set @c:=0; mysql> select id,@b:=IF(id=@a+1,id,concat(@a+1,"..",id-1)),@a:=id,@flag:=IF(@b=id,id,"MISS ING") from seq; +----+-------------------------------------------+--------+----------------- --------------+ | id | @b:=IF(id=@a+1,id,concat(@a+1,"..",id-1)) | @a:=id | @flag:=IF(@b=id,id,"MISSING") | +----+-------------------------------------------+--------+----------------- --------------+ | 1 | 1 | 1 | 1 | | 2 | 2 | 2 | 2 | | 3 | 3 | 3 | 3 | | 4 | 4 | 4 | 4 | | 5 | 5 | 5 | 5 | | 6 | 6 | 6 | 6 | | 7 | 7 | 7 | 7 | | 8 | 8 | 8 | 8 | | 9 | 9 | 9 | 9 | | 12 | 10..11 | 12 | MISSING | | 13 | 13 | 13 | 13 | | 14 | 14 | 14 | 14 | | 15 | 15 | 15 | 15 | | 16 | 16 | 16 | 16 | | 17 | 17 | 17 | 17 | | 18 | 18 | 18 | 18 | | 19 | 19 | 19 | 19 | | 22 | 20..21 | 22 | MISSING | | 24 | 23..23 | 24 | MISSING | | 25 | 25 | 25 | 25 | | 26 | 26 | 26 | 26 | | 27 | 27 | 27 | 27 | | 28 | 28 | 28 | 28 | | 29 | 29 | 29 | 29 | +----+-------------------------------------------+--------+----------------- --------------+ 24 rows in set (0.00 sec)
To get the MISSING entries you would need to create a temporary table from that query then select where the @flag column = "MISSING". Maybe this is more efficient than the join previously suggested. Maybe mysql team would let HAVING be applied to the 'variably' created rows you could then add having flag_alias = "MISSING" project out just the rows that are missing (saving the need for temporary tables). you could also plug the 10..11 20..21 etc statements into a perl foreach loop (if you were using perl) to automatically create the inner numbers. Ric p.s. maybe there is a way of tricking it into using a having statement to project out the "MISSING" rows. ----- Original Message ----- From: "Kevin Fries" <[EMAIL PROTECTED]> To: "'mos'" <[EMAIL PROTECTED]>; <[EMAIL PROTECTED]> Sent: Thursday, May 30, 2002 10:56 PM Subject: RE: Finding holes in autoinc sequences > A simple and fast way to find the gaps is to use a self LEFT JOIN, such as: > > select a.id from seq a left join seq b on a.id + 1 = b.id > where b.id is null; > > > The result set will show any row in seq where there was no record with ID > one greater than that record's value. > You'll get back the last row, and any rows which don't have a next-higher > neighbor. > > To get my example above to work, use: > > create table seq ( id int auto_increment not null primary key); > > insert into seq values(); ** repeat to get rows 1..30. ** > > delete from seq where id between 10 and 11; > delete from seq where id between 20 and 21; > delete from seq where id = 23; > > select a.id from seq a left join seq b on a.id + 1 = b.id > where b.id is null; > > +----+------+ > | id | id | > +----+------+ > | 9 | NULL | > | 19 | NULL | > | 22 | NULL | > | 30 | NULL | > +----+------+ > > Note that this doesn't show where the gaps end. You can further enhance the > query by looking backward as well...getting fancy output: > > select a.id, case when c.id is null and b.id is null then '<>' else (case > when c.id is null then '<' else (case when b.id is null then '>' else '' > end) end) end gaps > from seq a left join seq b on a.id + 1 = b.id left join seq c on a.id - 1 = > c.id > where b.id is null or c.id is null; > > +----+------+ > | id | gaps | > +----+------+ > | 1 | < | > | 9 | > | > | 12 | < | > | 19 | > | > | 22 | <> | > | 24 | < | > | 30 | > | > +----+------+ > > Note here that there's a gap between 9 and 12, between 19 and 22, and > between 22 and 24. > There's also a gap before 1, and one after 30, but this just tells us where > the range ends. > > nulled Outer joins are very handy. > > Kevin Fries > > > > > > > -----Original Message----- > > From: mos [mailto:[EMAIL PROTECTED]] > > Sent: Thursday, May 30, 2002 1:18 PM > > To: [EMAIL PROTECTED] > > Subject: Finding holes in autoinc sequences > > > > > > I'm going to be tackling this problem in a few days and I > > wanted to bounce > > it off of a few MySQL heads first to see if it generates any > > ideas. (or > > sparks?<g>) > > > > Here's is the problem. I have an auto-inc column and rows > > will get deleted > > from the table and of course it will create a hole in the > > sequence which is > > fine. But I want to track which rows have been deleted by finding the > > holes. (I will probably keep track of the deleted rows as they get > > deleted, but occasionally I will need to verify this by > > scanning the table.) > > > > Example: > > > > Original squence of Rcd_Id: 1,2,3,4,5,6,7,8,9,10 > > > > After deleting rows 5 and 9 we get: > > Rcd_Id: 1,2,3,4,6,7,8,10 > > > > Now is there any SQL statement that I can use to quickly and > > efficiently > > find the 2 missing rows in this example? The only thing I've > > come up with > > is to write a PHP program to loop through the Rcd_Id's in > > order and see > > which ones are missing (the query would fetch 10k rows at a > > time so it > > doesn't consume too much memory). The table could get rather > > large (>1m > > rows) and I need something that doesn't consume a lot of > > memory or time. > > Does anyone have any ideas? TIA > > > > Mike > > > > > > > --------------------------------------------------------------------- > Before posting, please check: > http://www.mysql.com/manual.php (the manual) > http://lists.mysql.com/ (the list archive) > > To request this thread, e-mail <[EMAIL PROTECTED]> > To unsubscribe, e-mail <[EMAIL PROTECTED]> > Trouble unsubscribing? Try: http://lists.mysql.com/php/unsubscribe.php > --------------------------------------------------------------------- Before posting, please check: http://www.mysql.com/manual.php (the manual) http://lists.mysql.com/ (the list archive) To request this thread, e-mail <[EMAIL PROTECTED]> To unsubscribe, e-mail <[EMAIL PROTECTED]> Trouble unsubscribing? Try: http://lists.mysql.com/php/unsubscribe.php