查询以查找列中具有重复字符的行

时间:2021-07-08 17:21:56

标签: sql sql-server

我的数据库是 SQL server 2019。我的表中有一个电话号码列,我必须找到最终用户输入的无效电话号码。一个这样的坏数据是 9999999999。目前我正在这样查询以识别这些值。

SELECT * FROM mytable WHERE PHN_NUM IN ('999999999','111111111','22222222','333333333')

有人可以帮助进行逻辑查询以找到这一点而不提及所有这些不良数据吗?

3 个答案:

答案 0 :(得分:1)

如果您想删除所有字符都相同的电话号码,那么一种方法是replace()

where replace(PHN_NUM, left(PHN_NUM, 1), '') = ''

即替换第一个看到的字符。如果没有,则所有字符都相同。

答案 1 :(得分:0)

几天前我创建了一个函数,可以很好地处理这种类型的事情。 使用 ngrams8k 我创建了一个名为 SequenceIsland 的函数(是的,需要一个更好的名字)......它的工作原理是这样的:

DECLARE @string VARCHAR(1000) = 'blah.. 111111111... 222222222... 33333333333...';
SELECT  sg.ItemIndex, sg.ItemLen, sg.Item
FROM    dbo.SequenceIsland8k(@string) AS sg

结果:

ItemIndex  ItemLen  Item
---------- -------- ----------------
1          1        b
2          1        l
3          1        a
4          1        h
5          2        ..
7          1         
8          9        111111111
17         3        ...
20         1         
21         9        222222222
30         3        ...
33         1         
34         11       33333333333
45         3        ...

它通过重复 0 次或更多次的值标记一个字符串,我称之为 序列岛。该函数返回“岛”、字符串中的位置及其长度。现在,您可以通过添加以下内容按长度过滤:WHERE sg.ItemLen > 3 表明存在三个候选者 - 位置 8、31 和 34

ItemIndex   ItemLen   Item
----------- --------- ------------
8           9         111111111
21          9         222222222
34          11        33333333333

你也可以用它做其他事情,比如删除或屏蔽数据;例如

DECLARE @string VARCHAR(1000) = 'blah.. 111111111... 222222222... 33333333333...';

SELECT  NewString = STRING_AGG(IIF(sg.ItemLen > 3 AND sg.token LIKE '[0-9]',
                              '<SomeNumber>',sg.Item),'') WITHIN GROUP (ORDER BY sg.ItemIndex)
FROM    samd.SequenceIsland8k(@string) AS sg;

退货:

blah.. <SomeNumber>... <SomeNumber>... <SomeNumber>...

功能:

CREATE OR ALTER FUNCTION dbo.SequenceIsland8k -- AKA SEQUENCE GRAMS (S-Grams)
(
  @string  VARCHAR(8000)
)
RETURNS TABLE WITH SCHEMABINDING AS RETURN
SELECT 
  Token        = ng.Token,
  ItemNumber = ROW_NUMBER() OVER (ORDER BY ng.Position),
  ItemIndex  = ng.Position,
  ItemLen    = i.Ln,
  Item       = item.Txt
FROM (
  SELECT
    ng.Position, ng.Token, IIF(LAG(ng.Token,1) OVER (ORDER BY ng.Position) = ng.Token,0,1)
  FROM   dbo.ngrams8k(@string,1) AS ng)                  AS ng(Position,Token,ngMatch)
CROSS APPLY (VALUES(SUBSTRING(@string,ng.Position,8000))) AS s(St) -- This Suffix
CROSS APPLY (VALUES(PATINDEX('%[^'+ng.Token+']%',s.St)))  AS nxt(C)
CROSS APPLY (VALUES((LEN(@string)+2)-ng.Position))        AS final(Ln)
CROSS APPLY (VALUES(ISNULL(NULLIF(nxt.C,0),final.Ln)-1))  AS i(Ln) -- Item Len
CROSS APPLY (VALUES(SUBSTRING(@string,ng.Position,i.Ln))) AS item(Txt)
WHERE       ng.ngMatch = 1;

答案 2 :(得分:0)

另一种选择是在字符串中搜索与第一个不匹配的任何字符:

psql