2009-08-03 7 views
3

nous un champ de phonenumber dans notre base de données et je voudrais faire une simple requête de recherche comme:SQL - Query Phonenumber qui sont stockés de manière incompatible

SELECT * FROM TABLE WHERE Phonenumber = '555123456' 

Mais depuis les phoneNumbers sont entrés par les utilisateurs et ne sont pas normalisés, nous ne savons pas vraiment à quoi ils ressemblent.

pourrait être:

  • + 555-123456

ou

  • (555) 123 456

ou

  • 555-12-34-56

ou quelque chose complety différent.

La seule chose certaine est que tous les nombres donnés devraient être là dans le bon ordre. Est-il possible de construire une requête autour de cela?

+0

Quel RDBMS utilisez-vous? – Quassnoi

+1

SQL Server 2005 –

Répondre

0

Comme je ne sais pas ce que vous cherchez SGBDR, je vais donner la façon la plus générique:

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

Cela suppose que tous les numéros de téléphone sont longueur au moins égale (en chiffres).

+1

La longueur doit être exactement égale. Cela va également correspondre à quelque chose comme '55555555123456' – Quassnoi

+0

@Quassnoi: D'où je mets dans la clause sur les numéros de téléphone doivent être égaux en chiffres. Sans le SGBDR du PO, cependant, c'est la meilleure solution générique. – Eric

+0

Cela pourrait avoir un impact sur les performances car les index sont strictement limités (ou pas du tout) avec les clauses LIKE. – Nate

5

En Oracle:

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

En 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' 

, ou, si vous voulez voir la valeur de téléphone normalisée,

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' 

Cependant, vous feriez mieux de créer une autre colonne pour les valeurs de téléphone normalisées, le remplir dans un déclencheur et l'indexer, de sorte que vous pouvez q plus efficacement.

3

Vous pouvez essayer quelque chose comme:

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

Remplacer une valeur non numérique avec une chaîne vide.

5

Si vous pouvez modifier la table (en supposant que ce soit SQL Server 2005 et plus), vous pouvez ajouter une colonne calculée à votre table et la conserver. Cette colonne pourrait contenir une représentation "nettoyée" de votre champ "phonenumber".

Quelque chose comme ceci:

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

puis:

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

Maintenant, votre version de votre numéro de téléphone "CleanedPhone" colonne aurait toujours contenu un "nettoyé" - toujours quelque chose comme: 555123456.

Comme il s'agit d'un champ PERSISTED, vous ne subissez pas de pénalité de performance lors de l'interrogation, soit - la valeur est créée et stockée dans votre table, et est disponible le comme une colonne normale.

Sur ce, vous pouvez maintenant interroger assez facilement.

Marc

1

Sinon, vous pouvez fixer vos pages d'entrée de données à dépouiller tous les caractères non numériques avant l'entrée dans la base de données, puis corriger toutes les données existantes pour dépouiller les chiffres. Ensuite, mettez une contrainte sur le champ qui nécessite que tous les caractères soient numériques. Ensuite, vous n'avez plus besoin de rechercher des caractères non numériques à chaque fois que vous souhaitez afficher un numéro de téléphone et vous pouvez facilement afficher l'interface utilisateur dans le format de votre choix. c'est-à-dire que vous n'avez pas mis les contrôles appropriés dans votre interface utilisateur) est mieux que de créer des solutions de contournement qui créent généralement des ralentissements de performance sans raison valable.

0

J'ai pris le concept de @ Eric et en utilisant un peu de code PHP cela fonctionnera avec n'importe quelle entrée de numéro de téléphone. (En supposant _GET $ a l'entrée de numéro de téléphone)

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

Cela se traduira par une valeur phone_formatted $ qui ressemble à '% x% x% x% x% x% x% x% x% x%', où x sont des nombres arbitraires.

Maintenant, vous pouvez utiliser la requête SQL:

phonenumber like $phone_formatted 

Si vous entrez 1231231234, il correspondra à des variations comme 123-123-1234, (123) 123-1234 et ainsi de suite. Si vous voulez aller plus loin, vous pouvez également supprimer tous les caractères non numériques (pour supprimer les parenthèses, les tirets et les espaces) de la valeur $ _GET ['phone'], de sorte que les entrées comme (123)) 123-1234 correspondra également à tous les cas ci-dessus.