views:

31

answers:

2

*First, thanks for the help in the first part of that question:

Situation again:

"I have in my table "mytable" fields, entryid (autoincrement) and roomid.. and I would like to delete all roomid = 1, except the last 3"

 entryid,  roomid
   1           1      
   2          55
   3           1
   4          12
   5           1
   6          44
   7           1
   8           3
   9           1

now i solved it with that:

// Delete older comments from room 1 (keep last 3 left)
// Step 1:
$sql_com = "SELECT id FROM `mytable` WHERE roomid = '1'";
$result = mysql_query ($sql_com); $num_rows = mysql_num_rows($result);   

// Step 2:
if ($num_rows > 3) {
  $sql_com = "SELECT id FROM `mytable` WHERE roomid = '1' ORDER BY id DESC LIMIT 3,1"; 
  $result = mysql_query ($sql_com);
  $row = mysql_fetch_array($result, MYSQL_NUM);
}

// Step 3: 
$sql_com = "DELETE FROM `mytable` WHERE roomid = '1' AND id < ".$row[0];
$result = mysql_query ($sql_com);

This works fine for now.

  1. Question: I needed to make Step 1 because without i would get an mysql error in step 2 at LIMIT 3,1 if there are less than 3 entries for roomid =1 in my table. (Limit 3,1 expect that there are minimum 3 entries). How could I solve that so I could remove step 1.

  2. MainQuestion: How to bring all this 3 Steps into ONE STEP :) Is that possible and how?

Thx Chris

p.s. just for info: this routine may be started 500 Times a Second with a Database of 3Million Entries. So it need to be resource friendly as possible.

+2  A: 
DELETE FROM `mytable` WHERE roomid = '1' AND roomid <= (SELECT * FROM (SELECT roomid FROM `mytable` WHERE roomid = '1' ORDER BY roomid DESC LIMIT 3,1) tmp);

Please notice if you remove "select * from (...) tmp)" you may get an error.

ERROR 1235 (42000): This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'

Also I think your code delete all rows except the last 4 ones (not 3).

Ehsan
@Ehsan: I like the workaround for the subquery LIMIT problem. However, your LIMIT means that only one row will be deleted at a time. Perhaps you mean something like this: `DELETE FROM \`mytable\` WHERE id IN (SELECT * FROM (SELECT id FROM \`mytable\` WHERE roomid = '1' ORDER BY id DESC LIMIT 3,18446744073709551615) tmp);`
Mike
@Mike: Your query will work, but with more overhead than mine. I limit my query in this way: `LIMIT 3,1`, so it will select the 4th biggest id in the table. and then I use `<` lightweight operator instead of complicated `in` operator.I tested my query and it works perfectly, but anyway thanks :-)
Ehsan
@Ehsan: Sorry, my mistake - I like what you've done. I tried it and it didn't delete anything, but I've now realised that your inner SELECT is testing for `id = 1` instead of `roomid = 1`. With that change, it works well.
Mike
@Mike: you're right, I tested it on another table that I already have, and I did forget to rename that field.
Ehsan
@Ehsan: +1 for handy subquery LIMIT workaround :-)
Mike
Hi Ehsan, thx your code works fine (just change WHERE id = '1' ORDER BY INTO WHERE roomid = '3' ORDER BY) (its about the roomid :) .. no i will have to make a runtime check whats faster :)
christian Muller
@Mike: thanks, +1 for you :-)@Christian: Edited
Ehsan
AND .. "ORDERY BY roomid" has to be "ORDER BY id" :) FINAL its: DELETE FROM `mytable` WHERE roomid = '1' AND id <= (SELECT * FROM (SELECT id FROM `mytable` WHERE roomid = '1' ORDER BY id DESC LIMIT 3,1) tmp);
christian Muller
You may like to help me with my final question :) :)http://stackoverflow.com/questions/3317089/mysql-select-and-where-over-several-tables-very-tricky
christian Muller
+1  A: 
DELETE mytable FROM mytable
JOIN (
  SELECT id FROM mytable
  WHERE roomid = 1
  ORDER BY id DESC
  LIMIT 3,18446744073709551615
) AS t2
ON mytable.id = t2.id;
Mike