Форматирование номера телефона в формате США (###) ### - #### - PullRequest
0 голосов
/ 07 октября 2019

Я пытаюсь переформатировать около 1000 телефонных номеров в базе данных SQL Server в американский формат (###) ###-####

В настоящее время телефонные номера отформатированы разными способами, начиная с ##########, ###-###-####, один ###)-###-####. Существует также один с шестью цифрами.

В качестве первого шага я пытался выделить числа во всех этих строках, но он просто возвращает то же, что и раньше.

select SUBSTRING(phone, PATINDEX('%[0-9]%', phone), LEN(phone)) from people

Как мне лучше всего написать запрос, который бы отформатировал их все как (###) ###-####?

ожидаемый результат:

(555) 222-3333
(555) 444-3030
(555) 092-0920
(555) 444-4444

Ответы [ 2 ]

1 голос
/ 07 октября 2019

Так как одно предложение уже было сделано и предложение выделять числа в строке использует цикл while, мне нужно опубликовать альтернативу тому, который не использует циклов. Вместо этого он использует таблицу подсчета или чисел. Есть много решений для тех. Мне нравится использовать представление, которое молниеносно и имеет нулевое чтение.

Вот моя версия таблицы подсчета.

create View [dbo].[cteTally] as

WITH
    E1(N) AS (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)),
    E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
    E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max
    cteTally(N) AS 
    (
        SELECT  ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4
    )
select N from cteTally

Далее нам понадобится табличная функция для удаления символовэто не числа, использующие нашу таблицу подсчета. Это также очень быстро, потому что мы используем нашу таблицу подсчета вместо циклов.

create function GetOnlyNumbers
(
    @SearchVal varchar(8000)
) returns table as return

    with MyValues as
    (
        select substring(@SearchVal, N, 1) as number
            , t.N
        from cteTally t 
        where N <= len(@SearchVal)
            and substring(@SearchVal, N, 1) like '[0-9]'
    )

    select distinct NumValue = STUFF((select number + ''
                from MyValues mv2
                order by mv2.N
                for xml path('')), 1, 0, '')
    from MyValues mv

Теперь, когда мы выполнили всю работу, мы можем сосредоточиться на поставленной задаче. Так как вы не предоставили никаких образцов данных, я просто составил некоторые вещи. Я не совсем уверен, является ли это репрезентативным для ваших данных или нет, но это работает с образцами данных, которые я создал.

if OBJECT_ID('tempdb..#Something') is not null
    drop table #Something

create table #Something(SomeVal varchar(100))

insert #Something values
('Maybe you have other stuff in here. 5552223333 additional characters can cause grief')
, ('321-654-9878')
, ('123)-333-4444')
, ('1234567')

select replace(format(try_convert(bigint, n.NumValue), '(###) ###-####'), '() ', '')
    , n.NumValue
from #Something s
cross apply dbo.GetOnlyNumbers(s.SomeVal) n

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

(555) 222-3333
(321) 654-9878
(123) 333-4444
123-4567
0 голосов
/ 07 октября 2019

Если это переформатирование чего-то, что будет использоваться многократно, тогда можно было бы создать UDF, предложенный @GSerg.

Если это только однократная очистка, вы можете датьэто попытка.

Сначала замените все числа пустыми строками на ряд вложенных функций REPLACE ().

DECLARE @PhoneNumbers TABLE (

Number varchar (20))

INSERT INTO @PhoneNumbers VALUES ('(888-239/1239')
INSERT INTO @PhoneNumbers VALUES ('222.1234')

SELECT 
REPLACE(
    REPLACE(
        REPLACE(
            REPLACE(
                REPLACE(
                    REPLACE(
                        REPLACE(
                            REPLACE(
                                REPLACE(
                                    REPLACE(Number, '0', '')
                                , '1', '')
                            , '2', '')
                        , '3', '')
                    , '4', '')
                , '5', '')
            , '6', '')
        , '7', '')
    , '8', '')
, '9', '')
FROM @PhoneNumbers

Затем возьмите эти нечисловые символы и вставьте их каждыйв своей собственной вложенной функции REPLACE () и отформатируйте результат. Вам придется иметь дело с каждой длиной индивидуально. Если у вас есть только 7 цифр, и вы хотите отформатировать его так, чтобы он содержал 10 цифр, что вы хотите, чтобы эти дополнительные 3 цифры были. Это будет обрабатывать 10-значные телефонные номера.

SELECT FORMAT(x.NumbersOnly, '(###) ###-####')
FROM 
(
    SELECT 
    CONVERT(BIGINT,
        REPLACE(
            REPLACE(
                REPLACE(
                    REPLACE(Number, '(', '')
                , '-', '')
            , '/', '')
        , '.', '')
    ) AS NumbersOnly
    FROM @PhoneNumbers
) x
WHERE LEN(x.NumbersOnly) = 10

Вот это dbfiddle .

...