MySQL删除语句基于具有多个返回值的子选择,同时为每个唯一值保留500条记录

时间:2016-10-04 00:21:09

标签: mysql sql subquery limit sql-delete

基于具有多个返回值的子选择的MySQL删除语句。

以下是我现在正在做的事情:

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
);

这很好用,但我想动态选择各个IP地址:

SELECT peerhost FROM `dnsstats` GROUP BY peerhost;

..并根据返回的值删除。

这是我从上一个问题得到的:

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条记录

知道我能做些什么来使这项工作?谢谢!

原始问题:MySQL delete statement based on sub-select with multiple return values

1 个答案:

答案 0 :(得分:1)

我会使用变量来做到这一点。以下列举了每个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行以外的所有行。