mysql - 每组只保留最新的 200 条记录

标签 mysql sql

我有一个包含列的表格 编号 |姓名 |日期 |组..

我想做的是删除每个组中计数超过 200 的所有旧记录。

例如,我有一个名为“shoes”的组,其中有 400 条记录 “giftcard”有300条记录,“electronics”有100条记录等等

因此,在运行 SQL 查询后,我希望每个组(鞋子、礼品卡、电子产品等)的数量小于或等于 200。 要删除的记录是按日期或 ID(自动递增)标识的旧记录。 因此,将删除“shoes”组中的 200 条记录,这些记录比保留的记录旧或 ID 小于保留的记录。

最佳答案

这类问题在 MySQL 中有点不方便,因为它们没有实现像 ROW_NUMBER() 这样的 SQL-99 窗口函数。 MySQL 在 8.0 版本之前不支持此功能。

这是一个在单个 SQL 语句中适用于 MySQL 5.7 和更早版本的解决方案,并且只能为每个组中大于 200 的成员进行选择。它使用名为 user variables 的 MySQL 功能,它们在您的查询过程中逐行保留它们的值(value)。

DELETE f FROM foo AS f
JOIN (SELECT id, IF(@g = `group`, @rn:=@rn+1, @rn:=1) AS row_number, @g:=grp
        FROM foo, (SELECT @g:=null, @rn:=0) _init
        ORDER BY `group`, date desc) AS r
ON f.id = r.id AND r.row_number > 200;

在你运行这个(或任何删除数据的东西!)之前,我建议你了解它是如何工作的,并用等效的 SELECT 测试它以确保它正在选择你想要删除的行。

我用较小的数据集对此进行了测试。这是我在没有过滤的情况下运行它时的数据:

SELECT f.id, f.`group`, r.row_number FROM foo AS f
JOIN (SELECT id, IF(@g = `group`, @rn:=@rn+1, @rn:=1) AS row_number, @g:=grp
        FROM foo, (SELECT @g:=null, @rn:=0) _init
        ORDER BY `group`, date desc) AS r
ON f.id = r.id;

+----+--------+------------+
| id | group  | row_number |
+----+--------+------------+
|  1 |      1 |          1 |
|  2 |      1 |          2 |
|  3 |      1 |          3 |
|  5 |      1 |          4 |
| 11 |      1 |          5 |
|  4 |      2 |          1 |
| 10 |      2 |          2 |
|  8 |      2 |          3 |
|  7 |      3 |          1 |
|  6 |      3 |          2 |
| 12 |      3 |          3 |
|  9 |      4 |          1 |
+----+--------+------------+

这是跳过每组前 2 个的 SELECT:

SELECT f.id, f.`group`, r.row_number FROM foo AS f
JOIN (SELECT id, IF(@g = `group`, @rn:=@rn+1, @rn:=1) AS row_number, @g:=grp
        FROM foo, (SELECT @g:=null, @rn:=0) _init
        ORDER BY `group`, date desc) AS r
ON f.id = r.id AND r.row_number > 2;

+----+-------+------------+
| id | group | row_number |
+----+-------+------------+
|  3 |     1 |          3 |
|  5 |     1 |          4 |
| 11 |     1 |          5 |
|  8 |     2 |          3 |
| 12 |     3 |          3 |
+----+-------+------------+

关于mysql - 每组只保留最新的 200 条记录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25872968/

相关文章:

php - 如何在单个 MySQL 语句中使用 GROUP_CONCAT 和 UNION

SQL CHECKSUM_AGG(BINARY_CHECKSUM(*)) 对具有相似内容的 2 个不同表给出相同的结果

python - 使用 DJANGO 框架进行 INNER JOIN

java - MySQL - Java 和 MySQL 过程和函数的集成问题

mysql - 如何在函数内使用动态查询

mysql - 为什么 INNER JOIN 不等于 (!=) 永远挂起

php - onbeforeprint() 和 onafterprint() 等同于非 IE 浏览器

php - 尝试将 JSON 数据传递给 Highcharts 但没有成功

sql - 左连接返回较少的行

php - 在 PHP 中向站点添加支付方式和托管