mysql удаляет все строки и сохраняет последние x слева [часть 2]

0

* Во-первых, спасибо за помощь в первой части этого вопроса:

Ситуация снова:

"У меня в таблице" mytable "поля, entryid (автоинкремент) и roomid.. и я хотел бы удалить все roomid = 1, за исключением последних 3"

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

теперь я решил это с этим:

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

Теперь это отлично.

  • Вопрос: Мне нужно сделать шаг 1, потому что без того, что я получу ошибку mysql на шаге 2 в LIMIT 3,1, если в таблице 1 есть меньше 3 записей для roomid = 1. (Предел 3,1 ожидает, что минимально 3 записи). Как я могу решить это, чтобы я мог удалить шаг 1.

  • MainQuestion: как привести все эти 3 шага в ОДИН ШАГ:) Это возможно и как?

спасибо Крис

p.s. просто для информации: эта процедура может быть запущена 500 раз в секунду с базой данных из 3 миллионов записей. Поэтому он должен быть максимально дружелюбным к ресурсам.

Теги:

2 ответа

2
Лучший ответ
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);

Обратите внимание, если вы удалите "select * from (...) tmp)" вы можете получить сообщение об ошибке.

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

Также я думаю, что ваш код удалит все строки, кроме последних 4 (не 3).

  • 0
    @Ehsan: мне нравится обходной путь для проблемы LIMIT подзапроса. Тем не менее, ваш LIMIT означает, что только одна строка будет удалена за раз. Возможно, вы имеете в виду что-то вроде этого: DELETE FROM `mytable` WHERE id IN (SELECT * FROM (SELECT id FROM `mytable` WHERE roomid = '1' ORDER BY id DESC LIMIT 3,18446744073709551615) tmp);
  • 0
    @Mike: Ваш запрос будет работать, но с большими накладными расходами, чем мой. Я ограничиваю свой запрос следующим образом: LIMIT 3,1 , поэтому он выберет 4-й по величине идентификатор в таблице. а затем я использую < легкий оператор вместо сложного in операторе. Я проверил мой запрос, и он отлично работает, но все равно спасибо :-)
Показать ещё 7 комментариев
1
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;

Ещё вопросы

Сообщество Overcoder
Наверх
Меню