2014-02-08 2 views
0

В настоящее время я использую следующее решение для проверки количества записей, а затем удалить последний из них, который превышает лимит. Псевдокод:Проверить количество строк и удалить последний, который превышает лимит

var count = SELECT COUNT(*) AS count FROM table WHERE user_id = ?; 

if (count > LIMIT) { // e.g [LIMIT == 5] 
    DELETE FROM table WHERE user_id = ? ORDER BY last_activity LIMIT 1; 
} 

Проблема в том, что я не очень рад этому решению. Я бы предпочел или предпочел сделать все это, используя только один запрос sql.

Тип last_activity column DATETIME.

+0

чем проблема с использованием подзапросов? – abl

+0

@ 0101. , , Я смущен. Ваш запрос * удаляет * одну строку ('limit 1'), но в тексте говорится, что вы« должны содержать одну строку ». Что он? Хранить один или удалить один? –

+0

Извините, я подумал, что мне нужно удалить одну строку. Спасибо, что предупредили меня. – 0101

ответ

1

Вы можете использовать join в delete заявлении удалить все, кроме самой последней строки, когда есть более чем в пять рядов для пользователя:

delete t from table t join 
       (select user_id, max(last_activity) as mla 
       from table 
       group by user_id 
       having count(*) > 5 
      ) mla 
       on t.user_id = mla.user_id and 
       t.last_activity < mla.mla; 

Это делает это для всех пользователей. Для одного пользователя, добавьте where заявление:

delete t from table t join 
       (select user_id, max(last_activity) as mla 
       from table 
       where user_id = '?' 
       group by user_id 
       having count(*) > 5 
      ) mla 
       on t.user_id = mla.user_id and 
       t.last_activity < mla.mla; 

EDIT:

Чтобы удалить одну строку, просто использовать min() вместо max():

delete t from table t join 
       (select user_id, min(last_activity) as mla 
       from table 
       where user_id = '?' 
       group by user_id 
       having count(*) > 5 
      ) mla 
       on t.user_id = mla.user_id and 
       t.last_activity = mla.mla; 
+0

Настоятельно извиняйтесь за замешательство, запрос должен удалить только одну строку с наименьшим значением last_activity, поэтому ваши примеры не работают правильно, но в любом случае спасибо. – 0101

+0

У меня есть еще один вопрос. Этот запрос (подзапрос) выбирает user_id & last_activity, а затем удаляется строка, которая равна ..., но что, если бы я хотел выбрать только id вместо user_id и last_activity? Спасибо. Я знаю, что это не будет иметь никакого значения, но я хотел бы знать, как это работает. Спасибо – 0101

+0

@ 0101. , , Вы можете добавить что-то вроде 'where userid = (выберите user_id из таблицы, где id =?)' –

0

Чтобы держать все в одном запросе, вы могли бы использовать что-то вроде этого:

DELETE FROM table 
WHERE 
    user_id = ? 
    AND last_activity = (SELECT * FROM 
    (SELECT CASE WHEN COUNT(*)>5 THEN MIN(last_activity) END 
    FROM table 
    WHERE user_id = ?) s) 

подзапрос возвратит первый last_activity, если есть более 5 мероприятий, и DELETE запрос будет удалить его. В противном случае он вернет NULL, и никакая строка не будет удалена.

+0

Если я попробую этот запрос отдельно, сначала запрос «SELECT CASE ...», а затем запросы «DELETE FROM ...» работают правильно, но вместе я получаю сообщение об ошибке «Вы не можете указать таблицу целевой таблицы» для обновление в предложении FROM « – 0101

+0

@ 0101 исправлено, теперь должно быть хорошо – fthiella

Смежные вопросы