Как удалить все, кроме как сохранить N последних строк по продукту в таблице истории цен - PullRequest
2 голосов
/ 24 апреля 2020

У меня есть таблица в MySQL 5.7.26, где я храню историю продуктов, у меня нет столбца с автоинкрементом

+------------+---------------------+
| product_id | date_in             |
+------------+---------------------+
|     500 | 2020-04-24 07:10:52 |
|     500 | 2020-04-24 07:12:11 |
|     500 | 2020-04-24 07:16:25 |
|     500 | 2020-04-24 07:18:32 |
|     500 | 2020-04-24 07:18:42 |
|     500 | 2020-04-24 13:51:30 |
|     500 | 2020-04-24 14:01:22 |

|     501 | 2020-04-24 07:10:52 |
|     501 | 2020-04-24 07:12:11 |
|     501 | 2020-04-24 07:16:25 |
|     501 | 2020-04-24 07:18:32 |
|     501 | 2020-04-24 07:18:42 |
|     501 | 2020-04-24 13:51:30 |
|     501 | 2020-04-24 14:01:22 |
+------------+---------------------+

Я хочу сохранить только последние 2 строки истории для каждого продукта и удалите их все, чтобы он выглядел следующим образом

+------------+---------------------+
| product_id | date_in             |
+------------+---------------------+

|     500 | 2020-04-24 13:51:30 |
|     500 | 2020-04-24 14:01:22 |


|     501 | 2020-04-24 13:51:30 |
|     501 | 2020-04-24 14:01:22 |
+------------+---------------------+

Ответы [ 2 ]

1 голос
/ 24 апреля 2020

Вы можете использовать синтаксис удаления / объединения вместе с row_number() (для последнего требуется MySQL 8.0) `:

delete t
from mytable t
inner join (
    select 
        product_id, 
        date_in, 
        row_number() over(partition by product_id order by date_in desc) rn
    from mytable t
) t1 
    on  t1.product_id = t.product_id 
    and t1.date_in = t.date_in 
    and t1.rn > 2

В более ранних версиях мы можем элюировать row_number() с подзапросом - при условии отсутствия дубликатов на (product_id, date_in):

delete t
from mytable t
inner join (
    select 
        product_id, 
        date_in,
        (select count(*) from mytable t2 where t2.product_id = t1.product_id and t2.date_in >= t1.date_in) rn
    from mytable t1
) t1 
    on  t1.product_id = t.product_id 
    and t1.date_in = t.date_in 
    and t1.rn > 2;
0 голосов
/ 24 апреля 2020

Попробуйте это. Он будет работать во всех mysql версиях

DELETE p1 
FROM
    products p1
    JOIN (
    SELECT
        product_id,
        date_in 
    FROM
        (
        SELECT
            p3.product_id,
            p3.date_in,
            ( CASE @grouping WHEN p3.product_id THEN @rank := @rank + 1 ELSE @rank := 1 END ) AS rank,
            @grouping := p3.product_id 
        FROM
            products p3,
            ( SELECT @rank := 0, @grouping := 0 ) AS tt 
        ORDER BY
            p3.product_id,
            p3.date_in DESC 
        ) tt2 
    WHERE
        rank > 2 
    ) p2 ON p1.product_id = p2.product_id 
    AND p1.date_in = p2.date_in
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...