【问题标题】:Phone number lookups using incoming numbers of varying lengths, with or without prefixes使用不同长度的传入号码(带或不带前缀)查找电话号码
【发布时间】:2014-11-21 17:56:53
【问题描述】:

系统:
-呼叫中心电话系统:来电伴随来源号码,又名来电显示,又名“ANI”
-SQL Server 2005 - 将客户电话号码 ([cANI])、客户名称、位置等存储在表中的“数据仓库”[CustDataByANI]
- 存储过程 - 呼叫中心软件将呼叫者 ID(又名 ANI)作为参数传递给 SP,SP 使用它在 CustDataByANI 表上执行当前简单的 SELECT 语句....WHERE [cANI] = @ANI。
如果查询在 @ANI 和“查找表”中包含的 686K cANI 值之一之间找到完全匹配,则此方法非常有效。这种情况只有大约 12% 的时间发生。

目标:增加成功的“可能/可能”匹配的数量

重要提示:我们使用的是全局数据集,无法强制执行有关任一值长度的规则(参数 @ANI 或 [cANI] 中的值)。
案例一:
电话系统发送源号码“9876543210”,用作参数@ANI
该确切数字存在于 CustDataByANI 表的 [cANI] 列中(记录# 55555)
Select 语句从与记录 55555 关联的许多其他列返回值 超级简单:WHERE [cANI] = @ANI 成功。

案例2:
@ANI = '19876543210'(与上面相同,但以'1'开头)
在 CustDataByANI.cANI 中找不到完全匹配
[cANI] 中最接近的匹配项是“9876543210”(仍记录为 55555)
即使是孩子也会认识到,与案例 1 的唯一区别是参数 @ANI 中存在一个 1 位“前缀” - 也许它是一个长距离“标签”或国家/地区代码。
这样的前缀长度可能是 1 位或 2 位甚至 3 位数字……我们无法预测。我们不想考虑长于 3 的前缀,但在这种情况下,我们确实希望从记录 55555 中返回值,如案例 1。

案例 3:案例 2 的“反转”
@ANI = '9876543210'
在 CustDataByANI.cANI 中找不到完全匹配
[cANI] 中最接近的匹配项是“19876543210”(记录号 55555 现在有一个“1”前缀)
同样,我们假设这两者实质上是等价的。在这种情况下,由于前缀,[cANI] 值包含更长的序列,长度可能是 1 或 2 甚至 3 位……我们无法预测。我们不想考虑长于 3 的前缀,但在这种情况下,我们确实希望从记录 55555 中返回值,如案例 1。

同样,由于每个值(@ANI 和 [cANI])的长度可能存在差异以及我几乎完全缺乏 SQL 编程,我无法为存储过程编写 SELECT 语句来考虑所有 3 种情况。带有通配符的简单“LIKE”语句似乎失败了,我的脑袋正在旋转,以从右到左的方式“读取”@ANI 和 cANI 值的 CASE 标准、CONTAINS 甚至 REVERSE 策略。

我的梦想是返回两者之间的最佳可能匹配
我的愚蠢程序如下;非常感谢任何和所有的帮助!

顺便说一句,我的源表 CustDataByANI 确实包含一个 RevANI 列,它只是反向的 cANI 值。最初我认为解决方案可能在于反转 @ANI 参数值并在 [RevANI] 列中找到最大匹配,从而在每个列的右侧留下任何通配符。但我仍然卡住了,不确定这是否是最好的策略....

USE [GCC]
GO
/****** Object:  StoredProcedure [dbo].[SP_GetCustDataByANI]    Script Date: 10/07/2014 07:47:34 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE [dbo].[SP_GetCustDataByANI] 
    @ANI varchar(80)
AS
BEGIN

    SET NOCOUNT ON;

--Remove leading zeros from the varchar @ANI. I chose this method rather than risking
--the undesirable introduction of exponential notation when long characters are converted to
--integers and back...

    IF ((LEN(@ANI) > 1) AND (LEFT(@ANI,1)= '0'))
    BEGIN
        SET @ANI = REPLACE(LTRIM(REPLACE(@ANI,'0',' ')),' ','0')
    END

    SELECT Id
        ,cANI
        ,cServiceClass
        ,cCompanyClass
        ,cContactName
        ,cContactDivision
        ,cContactDepartment
        ,cCompanyName
        ,cOrganizationName
        ,cContactCity
        ,cContactStateTerr
        ,cContactCountry
        ,cCompanyIsDistributor
        ,PrefAgentID
        ,PrefAgentID_SQUAL
        ,PrefRegionID_SQUAL
        ,VIP_CC
        ,VIP_TS
        ,TS_ACAT
    FROM [dbo].[CustDataByANI]
    WHERE ([cANI] = @ANI)

【问题讨论】:

  • 您是否考虑过使用 RIGHT(@ANI, 10) = [cANI]?
  • 是的....过去,我在处理美国专用电话号码时有这个“规则”。但是,我想在全球范围内使用相同的数据集,其中存在更多可变性。 (长度在 8 到 15 位之间的块)

标签: sql select case phone-number case-when


【解决方案1】:

如果您想让查询更快,您可以创建一个以相反顺序使用电话号码的附加列,在此列上创建索引,然后使用 LIKE 谓词查询号码,同时传递搜索到的电话号码以相反的顺序。这将使查询尽可能快。例如,对于您的示例数据,您可以将其存储在新的 ReversedPhoneNumber 列中:

6543211234     store as: 4321123456
16543211234    store as: 43211234561 
0016543211234  store as: 4321123456100

当您需要通过6543211234 进行查询时,只需将其反转并像这样在反转的列中查看

WHERE ReversedPhoneNumber LIKE `6543211234%`

这将匹配它存储的任何格式的数字,而且速度非常快,因为它是一种简单而快速的索引查找。 (类似于“开始于”操作的LIKE 将寻找索引以寻找巧合)。

关于您需要应用的附加规则,您比我们更了解数据。只需考虑所有可能的情况并进行一些测试,您就会得到需要应用的规则(不是为了加快速度,而是为了确保正确匹配)。

您可以在 ETL 过程中反转电话号码。

缺少细节以提供更好的建议。

注意:如果您无法向现有表添加列和索引,只需创建一个不同的表来保存与现有表相关的反转数字。您还可以添加触发器来维护此表

【讨论】:

  • 感谢您的建议。我确实有一个索引 ReversedPhoneNumber 列 [RevANI],它可以很好地配合您的提案。我需要 CASE WHEN THEN 语句的帮助,尤其是 LEN 限制。我想避免将“短”(可能
  • 您需要展示更多用例,以便我们提供更多有用的建议。这是定义工作规则的关键。
  • 我已经编辑了最初的帖子以包含 3 个案例。我担心 WHERE RevANI LIKE '@ANI%' 可能会失败案例 2。
  • 是的,这会失败,但这只是一个语法问题:WHERE RevANI LIKE @ANI+'%'。当然,你可以OR这两种情况。
猜你喜欢
  • 1970-01-01
  • 2012-10-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-05
  • 1970-01-01
相关资源
最近更新 更多