4

私は電話番号を持つ約130,000件のレコードを持つテーブルを持っています。数字はすべて +4311234567 のようにフォーマットされています。番号には、常に国際国コード、ローカル エリア コー​​ド、電話番号、場合によっては内線番号が含まれます。

テーブル内の発信者番号をチェックする Web サービスがあります。そのサービスはすでに機能しています。しかし今、クライアントは、誰かが会社から電話をかけた場合、その番号がデータベースに既に存在するが内線番号には含まれていない場合、サービスが何らかの結果を返すことを望んでいます。

テーブルの例。

   **id** | **電話番号** | **名前**   
| | 1 | +431234567 | A社  
| | 2 | +431234567890 | A社の従業員  
| | 3 | +4398765432 | B社

A 社の誰かが別の内線番号 (+43123456777 など) で電話をかけた場合、id1 が返されるはずです。しかし問題は、内線番号の桁数がわからないことです。3 桁、4 桁、またはそれ以上の桁数になる可能性があります。

文字列の種類のマッチングのパターンはありますか?

データは sql2005 データベースに保存されます。

ありがとう

編集:
crm システムから取得している電話番号。CRM の管理者と話しましたが、彼は別の形式でデータを送信しようとしています。

   **id** | **電話番号** |**内線** | **名前**   
| | 1 | +431234567 | | | A社  
| | 2 | +431234567 | 890 | A社の従業員  
| | 3 | +4398765432 | | | B社
4

7 に答える 7

4

保存された番号のどの部分が内線番号であるかを判断する方法はありますか?または、拡張なしの「基数」番号が格納されます。はいの場合、データベース内の番号(拡張子なし)が現在の番号のプレフィックスであるかどうかを確認できます。プレフィックスとは、先頭から始まる文字列の部分文字列を意味します。

しかし、データベースに拡張子が付いた数字しかなく、それに属する桁数を知る方法がない場合、正確な解決策を見つけることはできないと思います。

于 2010-05-04T13:26:28.787 に答える
2

内線番号の桁数が会社ごとに異なる可能性があり、数字の桁数が国や市外局番ごとに異なる可能性があることを考えると、これを効率的に行うのは難しい問題です。

データ テーブルを基数と内線番号に分割したとしても、受信番号を基数と内線番号に分割する必要があり、実際には複雑になっていると思います。

私が試してみたいことは次のとおりです。

元のフォーマット

  1. 着信番号をデータベースと照合してみてください。
    • 1 つのレコードに一致する場合は、特定の人物という答えが得られます。
    • 複数のレコードに一致する場合は、何か問題が発生しているため、失敗します。
    • それ以外の場合は、会社を見つける必要があります。
  2. 着信番号から末尾の数字を取り除き、これをデータベースと再度照合してください。
    • 桁数がしきい値 (おそらく 6 桁) を下回った場合、検索はおそらく失敗するはずです。これは、番号が見つからない場合に実行されるデータベース検索の数を制限するためです。
    • 一致するレコードがない場合は、この手順を再試行する必要があります。
    • 複数のレコードに一致する場合は、何か問題が発生しているため、失敗します。
    • 一致するレコードが 1 つだけの場合は、次善の回答である会社が得られます。

たとえば、「+43123456777」を検索する場合:

  • +43123456777 は 0 エントリに一致します。
  • +4312345677 は 0 エントリに一致します。
  • +431234567 は 1 つのエントリに一致します: 「会社 A」

このアプローチの主な失敗モードは、会社が可変長の内線番号を持っている場合です。たとえば、431234567890 と 43123456789 の両方が有効な数値であるが、2 番目の数値のみがデータベースにある場合に何が起こるかを考えてみましょう。着信番号が 431234567890 の場合、43123456789 が誤って一致します。

分割形式

これはもう少し複雑ですが、より堅牢です。

  1. 着信番号をデータベースと照合してみてください。
    • 1 つのレコードに一致する場合、答えは会社です。
    • 複数のレコードに一致する場合は、拡張子のないエントリと一致し、会社が見つかりました。
    • それ以外の場合は、基本の会社番号と内線番号を見つける必要があります。
  2. 着信番号から末尾の数字を取り除き、これをデータベースと再度照合してください。
    • 桁数がしきい値 (おそらく 6 桁) を下回った場合、検索はおそらく失敗するはずです。これは、番号が見つからない場合に実行されるデータベース検索の数を制限するためです。
    • 一致するレコードがない場合は、この手順を再試行する必要があります。
    • それが 1 つのレコードと一致する場合、答えは会社です。
    • 複数のレコードに一致する場合は、会社の基本番号が見つかったので、内線番号がわかったので、特定の人を検索してみることができます。
  3. 元の着信番号の先頭から基数を取り除き、これを使用してその基数を持つレコードの拡張を検索します。
    • 正確に 1 つのレコードに一致する場合は、特定の人が見つかりました。
    • 特定の人物と一致しない場合は、拡張子のないエントリと一致すると、その会社が見つかりました。

たとえば、「+43123456777」を検索する場合:

  • +43123456777 は 0 エントリに一致します。
  • +4312345677 は 0 エントリに一致します。
  • +431234567 は、「empty:Company A」と「890:employee in company A」の 2 つのエントリに一致します。
  • これら 2 つの一致の中で、"77" は何も一致しないため、空の拡張子 "Company A" を返します。

実装に関する注意事項

前述のように、このアルゴリズムにはいくつかの効率上の問題があります。データベース ルックアップが高価な場合、特にデータベースに同様の番号が存在しない場合 (たとえば、着信番号がカザフスタンからのものであるが、カザフスタンがない場合)、電話番号の長さに関連する線形コス​​トが発生します。データベース内の数字 *8')。

ただし、いくつかの最適化を比較的簡単に追加できます。扱う企業のほとんどが 3 桁または 4 桁の内線番号を使用している場合は、最初に末尾の 4 桁を削除してから、答えが出るまでバイナリ チョップを行うことができます。これにより、多くの場合、15 桁の数字が 4 または 5 に減少し、最大で 6 回のルックアップになります。

また、選択を絞り込むたびに、データベース全体から選択するのではなく、前の選択からのみ選択することができます。

追加の実装メモ

Unreasonの答えがどのように機能するかを最終的に理解したので、それがはるかにシンプルでエレガントなソリューションであることがわかります. 着信番号でデータベース番号を探すのではなく、単純にデータベース番号を探すという単純さについて考えてみたいと思います。

私の唯一の懸念はtelephonenumber、データベース内のすべてでこれを実行すると、サーバーに過度の要求が課される可能性があることです。そのソリューションを最大のストレス下でベンチマークし、問題が発生するかどうかを確認することをお勧めします。そうでない場合は、それを使用してください。その場合は、単純な形式のアルゴリズムを実装して、ストレス テストを再度実行することを検討してください。それでもパフォーマンスが低すぎる場合は、二分探索の提案を試してください。

于 2010-05-04T15:36:22.163 に答える
2

データベースで電話番号を検索する代わりに、問題を逆にして、データベース内のすべての番号を調べて、着信番号と一致するか、接頭辞が付いているかどうかを確認できます。

発信者 ID から +431234567891 などの電話番号を取得すると仮定すると、

SELECT name, id
FROM Table
WHERE CHARINDEX(telephonenumber, "+431234567891") > 0;

会社が返され、+431234567890 の場合は 2 つのレコードが返されます

  • 会社
  • 実際の延長

クライアント側から返された 2 つの行を処理できる場合は、上記で問題ありません。

データを前処理する方が (パフォーマンスに関して) 優れていますが、そのためには、データをより詳細に記述する必要があります。次に例を示します。

  • 内線番号は 3 桁と 4 桁のみです。
  • 基数は常に 9 桁または 10 桁です。
  • 内線のある会社の場合、常に少なくとも 1 つの内線番号を持っていますか?
于 2010-05-04T13:59:26.217 に答える
1

内線番号の桁数はPBX固有です。市外局番+電話番号の桁数は国/通信事業者によって異なります。

これを行う1つの方法は、たとえば...などの追加のルールを定義することです。

+43123 | 12

... +43123で始まるものはすべて12桁の数字であり、それを超えるものはすべて拡張子です。これにより、(ハードコードされた代わりに構成可能な)データを使用して、拡張子が始まる場所を指定できます。

別の方法は、「会社A」の例に示すように、拡張機能のある番号のエントリには、拡張機能のない対応する番号も存在​​する必要があると主張することです。

于 2010-05-04T13:25:24.457 に答える
1

電話番号システムに関する私の理解では、一方が他方のプレフィックスである場合、2 つの有効な/完全な番号は存在できないということです。ここでよくあるいたずらは、あなたの番号を 11 05 32 か何かで教えることです。ここで、110 はドイツの緊急警察の番号です。

したがって、データベース構造を変更してデータを前処理できる場合は、同じプレフィックスを持つ番号を探すことができます (長い方が短い方から始まる場合は、最初に並べ替えます)。毎試合は

  • 基数 (最も短いもの)
  • 直通番号と内線番号 (すべて長いもの)

可能であれば、データベース内のそれらをマークして、検索を高速化します。

このアプローチは、共通のデフォルト拡張子がある場合には不十分です。ここでは、多くの企業が 1234567-0 のような番号を外部番号として発行しています。0 は 2 ~ 4 桁の内線番号に置き換えることができます。これらの場合、私のアプローチは不十分です-あなたのサンプルデータではうまくいきますか?

于 2010-05-04T13:28:53.527 に答える
1

さまざまな国の電話番号を扱っている場合、それはほとんど不可能です。同じ国内でも長さが変わることがよくあります。長さがわかっている場合 (または ChrisW のようにリストを維持したい場合) は、会社の電話番号を検索する前に LEFT(field, x) 関数を使用して電話番号を切り捨てることができます。結合を行っている場合は、すべての行で関数を実行する必要があるため、実行が非常に遅くなることに注意してください。

于 2010-05-04T13:30:19.923 に答える
-1

これは、さらに情報がなければ不可能です。テーブルが上記のように構成されている場合、システムには、どの部分が基本番号で、どの部分が拡張子であるかを知る手段がありません。したがって、「+439」で始まる任意の(不明な)番号に対して「会社 b」が返されます。

編集(@MarkBooth)

私は、追加情報がなければ不可能であるという私の主張を支持します。わかりやすくするために、データベースに次の情報があるとします。

...
+43316852132 - ....
+433168731 - Company A (reception)
+433168739999 - Company A, Mr. X
+433168911321 - ....
...

これらの番号の構造は +43 (316) 873 - 1 であり、プログラムはこれを認識していません。したがって、番号 +43316872133 (+43 (316) 87 21 33 with structure) が呼び出している場合 (これはデータベースにはありません)、あなた (そしてあなたのソフトウェア :)) はそれが会社 A に属しているかどうかを判断できません。情報。

唯一の解決策は、単純なプレフィックス検索を実行できる会社の「基本番号」を維持することです。

于 2010-05-04T13:29:38.300 に答える