tags:

views:

70

answers:

6

Hi, i have a table like

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

now I would like to delete ALL entries where roomid = 1 and keep the latest 3 from roomid = 1 left (best with just one command)

so finaly entryid: 1 & 3 came deleted and entryid 6, 7, 9 keeps staying (for sure all other roomid will still stay)

EDIT: Thanks for help. Bellow i Added my own Solution, for everyone interested

I started a new Question how to bring that into ONE command. You may help me there. Thanks

A: 

Something like

delete from TABLE 
where roomid=1 
   and entryid not in 
   (select entryid from TABLE where roomid=1 order by entryid desc limit 0, 3)

might work.

njk
Will not work for mysql, can not refer to table to delete records in where. Need 2 query
ERROR 1093: You can't specify target table 'TABLE' for update in FROM clause
Andomar
+1  A: 

You can store the ids of the superfluous rooms in a temporary table, and delete based on that:

create temporary table tmpTable (id int);

insert  tmpTable
        (id)
select  id
from    YourTable yt
where   roomid = 1
        and 3 <=
        (
        select  count(*)
        from    YourTable yt2
        where   yt2.roomid = yt.roomid
                and yt2.id > yt.id
        );

delete  
from    YourTable
where   ID in (select id from tmpTable);    

This results in:

ID  roomid
2   55
4   12
5   44
6   1
7   1
8   3
9   1
Andomar
+1: Feels like deja vu...
OMG Ponies
Nice if MySQL is the only technology at hand. But, IMO, this would be overkill if something else were available.
Jason McCreary
thanks.. but in my view if you have a large db it would need too much resources
christian Muller
@christian Muller: If you were deleting a million rows, a temporary table with one integer column would take up about 4 megabyte of RAM. MySQL won't even notice :)
Andomar
A: 

DELETE supports an ORDER BY and LIMIT clause, so it is possible. However, due to DELETE's referential restrictions and parameters of LIMIT you need two queries.

SELECT COUNT(*) AS total FROM table  WHERE roomid = 1;
-- run only if count is > 3
DELETE FROM table WHERE roomid = 1 LIMIT total - 3;

Please note this will probably require an intermediary technology. I have shown the queries for reference.

Jason McCreary
Interesting approach, but I don't think MySQL allows a variable after `limit`. You'd have to construct a dynamic SQL statement.
Andomar
@Andomar Definitely, as I noted, this is more or less pseudo SQL to emphasis the 2 query approach. It would require a helping technology (say, PHP) to construct the dynamic queries.
Jason McCreary
i work till now with two queries:// Delete older comments from that room > 100 $sql_com = "SELECT id FROM `mytable` WHERE roomid = '3' ORDER BY id DESC LIMIT 10,1"; if ($result = mysql_query ($sql_com)) {} else { echo ('Database SELECT ERROR, ' . mysql_error());} ; $row = mysql_fetch_array($result, MYSQL_NUM); $sql_com = "DELETE FROM `mytable` WHERE id < ".$row[0]; if ($result = mysql_query ($sql_com)) {} else { echo ('Database SELECT ERROR, ' . mysql_error());} ; but maybe it can be done better, just with one command
christian Muller
A: 

T-SQL guy here, but can t-sql do:

SELECT
    *
FROM 
    TABLE A

    LEFT JOIN (SELECT TOP 3 entryID FROM TABLE WHERE roomID = 1 ORDER BY entryID DESC) B
    ON A.entryID = B.entryID 
WHERE       
    A.roomID = 1 AND
    B.entryID IS NULL

Then replace the select with DELETE TABLE FROM...

?

ThatSteveGuy
I'm afraid T-SQL is way more powerful than what MySQL allows. This would generate the `ERROR 1093: You can't specify target table 'TABLE' for update in FROM clause` error
Andomar
+1  A: 
SET @deleting = (SELECT COUNT(*) FROM tbl WHERE roomid = 1) - 3;
-- run only if @deleting is > 0
PREPARE stmt FROM 'DELETE FROM tbl WHERE roomid = 1 ORDER BY entryid LIMIT ?';
EXECUTE stmt USING @deleting;
Max Toro
A: 

Thanks for all your Help.. I took them all together and use now this Solution :) For me this Step is closed. Thanks.

// 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);
christian Muller