前缀最佳匹配

nx7onnlm  于 2021-06-20  发布在  Mysql
关注(0)|答案(2)|浏览(420)

这就是我的设想。我有4个表:记录,提供者,路由,域,域。
域:id,name(类似于'example.com')
提供者:id,name(类似于“tlc”)
记录:电话号码(varchar),提供者id(提供者的外键)
路由\域:提供程序\ id(提供程序的外键)、域\ id(域的外键)和前缀(varchar)。
表格示例:

mysql> select id,name from domains;
+----+-----------------------+
| id | name                  |
+----+-----------------------+
|  1 | e164.arpa             |
|  3 | example.com           |
|  0 | localhost.localdomain |
|  4 | luigi.it              |
|  2 | tim.it                |
+----+-----------------------+

mysql> select id,name from providers where id in (9,10);
+----+----------+
| id | name     |
+----+----------+
|  9 | TIM      |
| 10 | VODAFONE |
+----+----------+    

mysql> select * from routing_domain;
+----+--------+-----------+-------------+
| id | prefix | domain_id | provider_id |
+----+--------+-----------+-------------+
|  3 | 3932   |         4 |           9 |
|  1 | 39320  |         2 |           9 |
|  2 | 39321  |         3 |          10 |
+----+--------+-----------+-------------+

现在,
给定一个提供程序id为9的电话号码“39320x”,我需要获得域id=2;
给定一个提供程序id为9的电话号码“39321x”,我需要获得域id=4;
所以,给定一个提供者id=9的电话号码“3932xx”,我需要进行一些最佳匹配搜索。开始搜索前缀6个字符,如果不匹配,尝试5个字符,以此类推,直到3个字符(393)。
我设法从电话号码中找到了正确的域名,只从前缀搜索到5个字符。
比如:

select * FROM records r
left join routing_domain rd on rd.prefix like SUBSTRING(r.phone_number,1,5) and r.provider_id = rd.provider_id 
left join providers p on p.id = rd.provider_id
left join domains d on d.id = rd.domain_id 
where r.name = 'xxxxxxxxxxxx';

有什么建议可以做这个最佳匹配吗?非常感谢!
更新
我试过这个:

select * FROM records r
left join routing_domain rd on on r.phone_number like concat(rd.prefix, '%') and r.provider_id = rd.provider_id 
left join providers p on p.id = rd.provider_id
left join domains d on d.id = rd.domain_id 
where r.name = 'xxxxxxxxxxxx';

现在,如果我搜索'39325x',有一个匹配前缀'3932',但如果我搜索'39320x',两个前缀将匹配,搜索返回2行。

lzfw57am

lzfw57am1#

一种选择是有一个子查询,为您提供最长的前缀匹配 provider_id 以及 prefix . 像这样:

select domain_id from routing_domain
where
  provider_id = 9
  and '39321xxxxxxx' like concat(prefix, '%')
  and length(prefix) =
  (    select max(length(prefix))
       from routing_domain
       where 
         provider_id = 9
         and '39321xxxxxxx' like concat(prefix, '%')
  )

看看我的小提琴。

pbwdgjma

pbwdgjma2#

http://sqlfiddle.com/#!9/2e36df/10号

SELECT r.*, 
       MAX(IF(rd.prefix = LEFT(r.phone_number,5),rd.prefix,
             IF(rd.prefix = LEFT(r.phone_number,4),rd.prefix,
                IF(rd.prefix = LEFT(r.phone_number,3),rd.prefix,''))))
FROM records r
LEFT JOIN routing_domain rd
ON r.provider_id = rd.provider_id
GROUP BY r.id

为了更接近你的尝试:
http://sqlfiddle.com/#!2017年9月2日

SELECT t.*, p.*, d.*
FROM (
  SELECT r.*, 
         MAX(IF(rd.prefix = LEFT(r.phone_number,5),rd.id,
               IF(rd.prefix = LEFT(r.phone_number,4),rd.id,
                  IF(rd.prefix = LEFT(r.phone_number,3),rd.id,'')))) as rd_id
  FROM records r
  LEFT JOIN routing_domain rd
  ON r.provider_id = rd.provider_id
  #WHERE r.phone_number = '393xxxxxxxxxx'
  GROUP BY r.id
  ) t
LEFT JOIN routing_domain rd
ON t.rd_id = rd.id
LEFT JOIN providers p 
ON p.id = rd.provider_id
LEFT JOIN domains d 
ON d.id = rd.domain_id

相关问题