【问题标题】:Deleting records with number repeating more than 5删除编号重复超过 5 的记录
【发布时间】:2023-04-03 07:56:01
【问题描述】:

我有一个长度为 9 的表中的数据,其中数据是这样的

999999969
000000089
666666689

我只想删除那些从 1 到 9 的任何数字重复超过 5 次的数据。

【问题讨论】:

  • 连续数字,或任何组合?即15552555 会被删除吗?
  • no 15552555 不会被删除...125555555 应该被删除

标签: sql regex database postgresql pattern-matching


【解决方案1】:

好的,所以这里的逻辑可以总结为:

  • 在任何给定数字中查找相同连续数字的最长序列;和
  • 如果最长值大于 5 位,则返回 true

对吗?

所以,让我们把它分成一系列连续的数字:

regress=> SELECT regexp_matches('666666689', '(0+|1+|2+|3+|4+|5+|6+|7+|8+|9+)', 'g');
 regexp_matches 
----------------
 {6666666}
 {8}
 {9}
(3 rows)

然后过滤最长的:

regress=> 

SELECT x[1] 
FROM regexp_matches('6666666898', '(0+|1+|2+|3+|4+|5+|6+|7+|8+|9+)', 'g') x 
ORDER BY length(x[1]) DESC 
LIMIT 1;

    x    
---------
 6666666
(1 row)

...但实际上,我们实际上并不关心这一点,只要任何条目的长度超过 5 位,所以:

SELECT x[1] 
FROM regexp_matches('6666666898', '(0+|1+|2+|3+|4+|5+|6+|7+|8+|9+)', 'g') x 
WHERE length(x[1]) > 5;

可以用作EXISTS 测试,例如

WITH blah(n) AS (VALUES('999999969'),('000000089'),('666666689'),('15552555'))
SELECT n
FROM blah
WHERE EXISTS (
    SELECT x[1] 
    FROM regexp_matches(n, '(0+|1+|2+|3+|4+|5+|6+|7+|8+|9+)', 'g') x 
    WHERE length(x[1]) > 5
)

这实际上非常有效并返回正确的结果(总是很好)。但可以通过以下方式进一步简化:

WITH blah(n) AS (VALUES('999999969'),('000000089'),('666666689'),('15552555'))
SELECT n
FROM blah
WHERE EXISTS (
    SELECT x[1] 
    FROM regexp_matches(n, '(0{6}|1{6}|2{6}|3{6}|4{6}|5{6}|6{6}|7{6}|8{6}|9{6})', 'g') x;
)

您可以在DELETE 中使用相同的WHERE 子句。

【讨论】:

  • 好像你忘记了正则表达式反向引用。
【解决方案2】:

使用back reference 的正则表达式可以简单得多

DELETE FROM tbl
WHERE  col ~ '([1-9])\1{5}';

就是这样。

解释

([1-9]) ... 数字从 1 到 9 的字符类,用括号括起来以供后面的反向引用。
\1 ... 反向引用第一个(并且仅在这种情况下)括号内的子表达式。{5} .. 正好(另一个)5 次,使其“超过 5”。

Per documentation:

后向引用 (\n) 匹配前一个匹配的相同字符串 由数字 n [...] 指定的带括号的子表达式 [...] 例如,([bc])\1 匹配 bbcc 但不匹配 bccb

SQL Fiddle demo.

【讨论】:

    【解决方案3】:

    在性能方面非常糟糕,但它应该可以工作:

    DELETE FROM YOURTABLE 
     WHERE YOURDATA LIKE '%111111%' 
        OR YOURDATA LIKE '%222222%' 
        OR YOURDATA LIKE '%333333%'
        OR YOURDATA LIKE '%444444%'
        OR YOURDATA LIKE '%555555%'
        OR YOURDATA LIKE '%666666%'
        OR YOURDATA LIKE '%777777%'
        OR YOURDATA LIKE '%888888%'
        OR YOURDATA LIKE '%999999%'
    

    【讨论】:

    • 实际上,性能可能没有看起来那么糟糕,因为LIKEtrigram index 结合使用仍然很快。但有了这么多替代方案,单个正则表达式可能会更快,当然也更短。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-28
    • 1970-01-01
    • 2021-03-17
    • 2016-10-07
    • 1970-01-01
    相关资源
    最近更新 更多