Удалите все строки, кроме 2 для каждого SID (в порядке убывания)

#mysql #sql-delete #mysql-5.5

Вопрос:

У меня есть таблица с такой структурой. Для каждого SID существуют разные идентификаторы элементов

 | sid | itemid |
|---| ---------|
| 1 | 20600    |
| 1 | 20598    |
| 1 | 20597    |
| 1 | 20596    |
| 1 | 20595    |
| 1 | 20594    |
...
...
| 2 | 19600    |
| 2 | 19598    |
| 2 | 19597    |
| 2 | 19596    |
| 2 | 19595    |
| 2 | 19594    |
...
...
 

Что мне нужно, так это удалить все, кроме последних 2 строк, с идентификаторами элементов, отсортированными по УБЫВАНИЮ.
Это тот результат, который я хочу получить:

 | sid | itemid |
|---| ---------|
| 1 | 20600    |
| 1 | 20598    |
| 2 | 19600    |
| 2 | 19598    |
 

Спасибо
Андреа

Комментарии:

1. Получите 2-е значение в подзапросе.

2. Привет @Akina, ты можешь попросить меня написать это?

3. Подзапрос должен: ВЫБРАТЬ идентификатор элемента ИЗ notifications_views_savedsearches_тест ПОРЯДОК ПО ИДЕНТИФИКАТОРУ элемента С ОГРАНИЧЕНИЕМ 2

Ответ №1:

 DELETE t0
FROM test t0
JOIN ( SELECT t1.sid,
              ( SELECT itemid
                FROM test t2
                WHERE t1.sid = t2.sid
                ORDER BY itemid DESC LIMIT 1,1 ) itemid
       FROM ( SELECT DISTINCT t3.sid
              FROM test t3 ) t1 ) t4 USING (sid)
WHERE t0.itemid < t4.itemid;
 

https://dbfiddle.uk/?rdbms=mysql_5.5amp;fiddle=c6d67da817ddbb9fb890693564bcd49c

Комментарии:

1. ты мой мужчина! Большое спасибо, это работает как заклинание!

Ответ №2:

В MySQL 8 мы можем попробовать удалить соединение с помощью ROW_NUMBER :

 DELETE t1
FROM yourTable t1
INNER JOIN
(
    SELECT sid, itemid,
           ROW_NUMBER() OVER (PARTITION BY sid ORDER BY itemid DESC) rn
    FROM yourTable
) t2
    ON t2.sid = t1.sid AND t2.itemid = t1.itemid
WHERE
    t2.rn > 2;
 

Комментарии:

1. Привет, Тим, моя версия клиента mysql-5.5.60

2. Этот запрос будет довольно сложно выполнить в MySQL 5.7 или более ранней версии.