SQL - запрос номера телефона, который хранится непоследовательно - PullRequest
3 голосов
/ 03 августа 2009

мы являемся полем номер телефона в нашей базе данных, и я хотел бы сделать простой запрос поиска, как:

SELECT * FROM TABLE WHERE Phonenumber = '555123456'

Но так как номера телефонов вводятся пользователями и не нормализуются, мы не знаем, как они выглядят.

Может быть:

  • + 555-123456

или

  • (555) 123 456

или

  • 555-12-34-56

или что-то совершенно другое.

Единственное, что определенно, это то, что все указанные числа должны быть там в правильном порядке. Можно ли построить запрос вокруг этого?

Ответы [ 6 ]

5 голосов
/ 03 августа 2009

ЕСЛИ вы можете изменить таблицу (при условии, что она SQL Server 2005 и выше), вы можете добавить вычисляемый столбец в таблицу и сохранить его. Этот столбец может содержать «очищенное» представление вашего поля «phonenumber».

Примерно так:

 create function dbo.CleanPhone(@phone varchar(100))
 returns varchar(100)
 with schemabinding
 as begin
   return
     replace(replace(replace(replace(replace(replace(@phone, ' ', ''), 
             '-', ''), '(', ''), ')', ''), '-', ''), '+', '')
 end

и затем:

alter table (yourtable)
 add cleanedPhone as dbo.CleanPhone(Phone) persisted

Теперь в вашем столбце «CleanedPhone» всегда будет «очищенная» версия номера вашего телефона - всегда что-то вроде: 555123456.

Так как это поле PERSISTED, при запросе вы не понесете потери производительности - значение создается и сохраняется в вашей таблице и доступно как обычный столбец.

Теперь вы можете легко запросить.

Марк

5 голосов
/ 03 августа 2009

В Oracle:

SELECT  *
FROM    mytable
WHERE   REGEXP_REPLACE(Phonenumber, '[^0-9]', '') = '5551234567'

В SQL Server 2005+:

WITH    digits AS
        (
        SELECT  1 AS digit
        UNION ALL
        SELECT  digit + 1
        FROM    digits
        WHERE   digit <= 100
        )
SELECT  *
FROM    mytable
WHERE   (
        SELECT  SUBSTRING(number, digit, 1) AS [text()]
        FROM    digits
        WHERE   SUBSTRING(number, digit, 1) BETWEEN '0' AND '9'
        FOR XML PATH('')
        ) = '5551234567'

или, если вы хотите увидеть нормализованное значение телефона,

WITH    digits AS
        (
        SELECT  1 AS digit
        UNION ALL
        SELECT  digit + 1
        FROM    digits
        WHERE   digit <= 100
        ),
        phones AS
        (
        SELECT  m.*,
                (
                SELECT  SUBSTRING(number, digit, 1) AS [text()]
                FROM    digits
                WHERE   SUBSTRING(number, digit, 1) BETWEEN '0' AND '9'
                FOR XML PATH('')
                ) AS nphone
        FROM    mytable m
        )
SELECT  *
FROM    phones
WHERE   nphone = '5551234567'

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

3 голосов
/ 03 августа 2009

Вы можете попробовать что-то вроде:

SELECT * FROM TABLE WHERE REPLACE( REPLACE( REPLACE( REPLACE( REPLACE(phone,'(','') ,')','') ,'-','') ,'+','') ,' ','') = '0398765432'

Заменить любое нечисловое значение пустой строкой.

1 голос
/ 03 августа 2009

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

1 голос
/ 03 августа 2009

Поскольку я не знаю, какую СУБД вы ищете, я дам наиболее общий способ:

phonenumber like '%5%5%5%1%2%3%4%5%6%'

Предполагается, что все телефонные номера имеют как минимум одинаковую длину (в цифрах).

0 голосов
/ 05 декабря 2016

Я взял концепцию @ Эрика и, используя немного кода PHP, это будет работать с любым вводом телефонного номера. (Предполагая, что $ _GET имеет введенный номер телефона)

    $phone                  = $_GET['phone'];
    $phone_formatted        = "%";
    for ($i=0; $i<strlen($phone); $i++) {
        $phone_formatted .= ($phone[$i] . "%");
    }

Это приведет к значению $ phone_formatted, которое выглядит как «% x% x% x% x% x% x% x% x% x%», где x - произвольные числа.

Теперь вы можете использовать SQL-запрос:

phonenumber like $phone_formatted

Если вы введете 1231231234, он будет соответствовать вариантам, таким как 123-123-1234, (123) 123-1234 и т. Д.

Если вы хотите продвинуться дальше, вы можете также удалить все нечисловые символы (чтобы убрать скобки, тире и пробелы) из значения $ _GET ['phone'], чтобы входные данные типа (123) 123-1234 также будет соответствовать всем вышеперечисленным случаям.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...