Моя БД - это SQL-сервер 2019. В моей таблице был столбец с номерами телефонов, и мне нужно было найти недопустимые номера телефонов, введенные конечными пользователями. Одним из таких неверных данных является 9999999999. В настоящее время я запрашиваю вот так, чтобы ...

0
Madhan 8 Июл 2021 в 20:21

4 ответа

Лучший ответ

Если вы хотите удалить телефонные номера, в которых все символы совпадают, можно использовать replace():

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

То есть замените первый видимый символ. Если ничего не осталось, то все символы одинаковы.

0
Gordon Linoff 8 Июл 2021 в 17:44

Другой вариант - поиск в строке любых символов, не соответствующих первому:

WHERE YourString NOT LIKE '%[^' + REPLACE(LEFT(YourString, 1), '\', '\\') + ']%' ESCAPE '\'
0
Charlieface 8 Июл 2021 в 20:45

Вы можете использовать любое регулярное выражение правильного номера телефона и отфильтровать недопустимые номера телефонов следующим образом

SELECT * FROM mytable WHERE PHN_NUM NOT LIKE '%[+\(\d+\)\s*\d+\s*-\s*\d+\s*-\s*\d+\s*]%'

http://sqlfiddle.com/#!18/9eecb/128395/0

Здесь я использую следующее регулярное выражение +\(\d+\)\s*\d+\s*-\s*\d+\s*-\s*\d+\s*

-1
Alexander Alexandrov 8 Июл 2021 в 18:05

Пару дней назад я создал функцию, которая довольно хорошо справляется с подобными вещами. Используя 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;
0
Alan Burstein 8 Июл 2021 в 18:24