如果记录的计数大于5,如何从表中删除记录

r7xajy2e  于 2021-06-21  发布在  Mysql
关注(0)|答案(4)|浏览(318)

我有下表:

id  systemid    value
1      1           0
2      1           1
3      1           3
4      1           4
6      1           9
8      1           10
9      1           11
10     1           12

现在我有8张 systemid = 1 所以现在我只想保留最新的3条记录(desc order)并删除其 systemid=1 我想要输出像:

id    systemid    value
 8     1            10
 9     1            11
 10    1            12

我只想删除systemid=1的旧记录,前提是它的计数大于5,并保留最近的3条记录。
如何在查询中执行此操作?

yqlxgs2m

yqlxgs2m1#

这将是一个很长的问题。您需要的是,对于每一个超过5条记录的系统标识,您都要删除排名低于3的记录。
我将把查询分开,并在最后使用它们的名称。
排名查询:abriviation is rq
在mysql中没有rownum之类的东西,希望这个查询返回从ghe开始到最后的记录。

SELECT 
               @rank := @rank + 1 as rank, 
               id, 
               system_id,
               value
       FROM table_name, (select @rank:=0) as rt
       order by system_id, value desc

这将对表中的每条记录进行排序,主要的好处是具有相同系统id的记录将按顺序依次排列

system_id       value      rank
               1.                     10.         1

                1.                     9.           2

                1.                     7.           3

                1.                     5.           4

                1.                     3.            5

                1.                      2.           6

                2.                    12.          7

                2.                    10.          8

                3.                     11.         9
                ........
                ......
                 3.                     1.          15

在本例中,对于系统\u id 1,我们只需要为系统\u id 3(9,10,11)保留前三个(1,2,3)记录
2过滤查询。缩写为:fq,因为您要根据计数5删除,我们需要这个额外的查询

SELECT
                 system_id
        FROM table_name
        GROUP BY system_id 
        having count(*) > 5

结果:

system_id
                        1
                        3

四、第三种查询方式:rqd
一个查询,知道我们应该从哪个等级开始对mysql中的每个系统id执行delete操作,我们需要再次重写第一个查询,但这里我将使用abriviation来保持答案简短。

SELECT 
               system_id,
               min_rank + 3  from_rank
        FROM (
               SELECT
                      RQ2.system_id,
                      min(RQ2.rank) as  min_rank
              FROM (rank_query) RQ2
              GROUP BY system_id) RS

对于同一个例子,我们将得到这个结果

system_id.    from_rank 
            1.                     4
            2.                     9    -- this record will be removed by the filter_query
            3.                     12

最终查询:
所以我们需要删除过滤查询中存在的,排名比排名大的记录。

DELETE FROM table_name WHERE 
              id in (
                 SELECT
                     RQ.id
                 FROM
                            rank_query RQ INNER JOIN filter_query FQ ON rq.system_id = FQ.system_id
                                                       INNER JOIN third_query RQD ON RQ.rank >= RQD.from_rank)

我希望这个想法能奏效抱歉,我用我的手机回答任何语法错误,我喜欢这种查询

twh00eeo

twh00eeo2#

如果并非总是有8条记录,并且希望从systemid=1的表中选择最后3条记录(不管有多少条记录),那么一个好方法是在sql语句中使用in选择器。
如果你能用这个语句来做这件事就好了

SELECT * FROM mytable WHERE id IN (SELECT id FROM `mytable` WHERE systemid=1 ORDER BY id DESC LIMIT 3)

然而,这在mysql中还不受支持,如果您尝试这样做,那么您将得到如下错误

...doesn't yet support 'LIMIT & IN/ALL/SOME subquery'

因此,您需要如下解决方法(使用select进行测试):

SET @myvar := (SELECT GROUP_CONCAT(id SEPARATOR ',') AS myval FROM (SELECT * FROM `mytable` WHERE systemid=1 ORDER BY id DESC LIMIT 3 ) A GROUP BY A.systemid);
SELECT * FROM mytable WHERE FIND_IN_SET(id,@myvar);

其工作方式(第一行)是设置一个名为@myvar的变量,如果id值为0,则该变量将最后3个值作为逗号分隔的字符串保存。对你来说

9,8,10

然后选择此字符串中“id”所在的行。
将“select*”替换为“delete from”以完成结果,这样您的查询将

SET @myvar := (SELECT GROUP_CONCAT(id SEPARATOR ',') AS myval FROM (SELECT * FROM `mytable` WHERE systemid=1 ORDER BY id DESC LIMIT 3 ) A GROUP BY A.systemid);
DELETE FROM mytable WHERE NOT FIND_IN_SET(id,@myvar);

我希望这有帮助。

fjaof16o

fjaof16o3#

您可以在查询中使用limit关键字指定偏移量,以便保留最新的5行。然而,根据mysql的文档,没有简单的方法来限制从一个偏移量到最后一个偏移量;相反,他们建议:
要检索从某个偏移量到结果集末尾的所有行,可以使用一些大的数字作为第二个参数。
所以这个sql应该做到:
从systemid=1的表中删除order by value desc limit 5454848

v1l68za4

v1l68za44#

尝试此操作以保留系统标识为1且计数大于5的最新三条记录: DELETE FROM <table_name> WHERE system_id = 1 AND value > 5 ORDER BY id DESC LIMIT 3

相关问题