MySQL 基于具有多个 return 值的子 select 删除语句,同时为每个唯一值保留 500 条记录
MySQL delete statement based on sub-select with multiple return values while retaining 500 records for each unique value
MySQL 删除基于具有多个 return 值的子 select 的语句。
这是我现在正在做的事情:
DELETE FROM `dnsstats` WHERE id NOT IN
(
SELECT id FROM
(
SELECT id FROM `dnsstats` WHERE peerhost = 'x.x.x.243' ORDER BY id DESC LIMIT 500
) foo
)
AND id NOT IN
(
SELECT id FROM
(
SELECT id FROM `dnsstats` WHERE peerhost = 'x.x.x.40' ORDER BY id DESC LIMIT 500
) foo2
)
AND id NOT IN
(
SELECT id FROM
(
SELECT id FROM `dnsstats` WHERE peerhost = 'x.x.x.50' ORDER BY id DESC LIMIT 500
) foo3
);
效果很好,但我想 select 动态地 select 个人 IP 地址,如下所示:
SELECT peerhost FROM `dnsstats` GROUP BY peerhost;
..并根据那些 returned 值删除。
这是我从上一个问题中得到的:
DELETE FROM `dnsstats` WHERE id NOT IN
(
SELECT id FROM
(
SELECT id FROM `dnsstats` WHERE peerhost in (
SELECT peerhost FROM `dnsstats` GROUP BY peerhost
) ORDER BY id DESC LIMIT 500
) foo
);
..但这给我留下了 500 条记录。我想为每个 peerhost
保留 500 条记录
知道我可以做些什么来完成这项工作吗?谢谢!
原问题:
我会使用变量来做到这一点。下面枚举每个peerhost
:
select s.*,
(@rn := if(@ph = peerhost, @rn + 1,
if(@ph := peerhost, 1, 1)
)
) as rn
from dnstats s cross join
(select @ph := '', @rn := 0) params
order by peerhost, id desc;
您可以在使用子查询的 delete
中使用它:
delete s
from dnstats s join
(select s.*,
(@rn := if(@ph = peerhost, @rn + 1,
if(@ph := peerhost, 1, 1)
)
) as rn
from dnstats s cross join
(select @ph := '', @rn := 0) params
order by peerhost, id desc
) es
on es.id = s.id
where rn > 500;
这将删除每个 peerhost
的前 500 行以外的所有行。
MySQL 删除基于具有多个 return 值的子 select 的语句。
这是我现在正在做的事情:
DELETE FROM `dnsstats` WHERE id NOT IN
(
SELECT id FROM
(
SELECT id FROM `dnsstats` WHERE peerhost = 'x.x.x.243' ORDER BY id DESC LIMIT 500
) foo
)
AND id NOT IN
(
SELECT id FROM
(
SELECT id FROM `dnsstats` WHERE peerhost = 'x.x.x.40' ORDER BY id DESC LIMIT 500
) foo2
)
AND id NOT IN
(
SELECT id FROM
(
SELECT id FROM `dnsstats` WHERE peerhost = 'x.x.x.50' ORDER BY id DESC LIMIT 500
) foo3
);
效果很好,但我想 select 动态地 select 个人 IP 地址,如下所示:
SELECT peerhost FROM `dnsstats` GROUP BY peerhost;
..并根据那些 returned 值删除。
这是我从上一个问题中得到的:
DELETE FROM `dnsstats` WHERE id NOT IN
(
SELECT id FROM
(
SELECT id FROM `dnsstats` WHERE peerhost in (
SELECT peerhost FROM `dnsstats` GROUP BY peerhost
) ORDER BY id DESC LIMIT 500
) foo
);
..但这给我留下了 500 条记录。我想为每个 peerhost
知道我可以做些什么来完成这项工作吗?谢谢!
原问题:
我会使用变量来做到这一点。下面枚举每个peerhost
:
select s.*,
(@rn := if(@ph = peerhost, @rn + 1,
if(@ph := peerhost, 1, 1)
)
) as rn
from dnstats s cross join
(select @ph := '', @rn := 0) params
order by peerhost, id desc;
您可以在使用子查询的 delete
中使用它:
delete s
from dnstats s join
(select s.*,
(@rn := if(@ph = peerhost, @rn + 1,
if(@ph := peerhost, 1, 1)
)
) as rn
from dnstats s cross join
(select @ph := '', @rn := 0) params
order by peerhost, id desc
) es
on es.id = s.id
where rn > 500;
这将删除每个 peerhost
的前 500 行以外的所有行。