我有以下查询:
DECLARE @phone varchar(50) = '972544123123'
SELECT top 1 prefix_number
FROM prefix_numbers
WHERE @phone LIKE LTRIM(RTRIM(prefix_number)) + '%'
ORDER BY len(prefix_number) DESC
它用于查找电话号码的最短前缀。这是不可扫描的,并且会导致表扫描。你对如何重写这个有什么想法吗?
其输出是972,其中所有可能的前缀都是9725&972.
假设:LTrim
是转移注意力的,所有前缀都存储为右填充的固定长度字符串。
以下代码应该能够在前缀表中的Prefix
上使用索引。它将目标电话号码(@Phone
(分解为从一个字符到号码长度的子字符串,然后使用可用前缀执行相等连接。使用top 1
和order by
,它检索最短(或最长(匹配(如果有的话(。
declare @Prefixes as Table ( PrefixId Int Identity, Prefix Char(50) );
insert into @Prefixes ( Prefix ) values
( '914' ), ( '972544' ), ( 'BR549' ), ( '972' );
select PrefixId, '''' + Prefix + '''' as Prefix -- Show blank padding.
from @Prefixes;
declare @Phone as VarChar(50) = '972544123123';
with
Substrings as (
select 1 as Length, Cast( Left( @Phone, 1 ) as VarChar(50) ) as TargetPrefix
union all
select Length + 1, Left( @Phone, Length + 1 )
from Substrings
where Length + 1 <= Len( @Phone )
)
-- select * from Substrings; -- Use this to see the intermediate results.
select top 1 P.PrefixId, P.Prefix
from @Prefixes as P inner join
Substrings as S on P.Prefix = S.TargetPrefix
order by S.Length; -- Ascending for shortest match, descending for longest match.
如果您有一个计数(或数字(表,使用它将字符串拆分为子字符串可能会更有效。