前缀最佳匹配 MySQL
Prefix best match MySQL
这就是我的设想。
我有 4 个表:记录、提供者、routing_domain、域。
- 域:id、名称(类似于 'example.com')
- 提供者:id、名称(类似于 'TLC')
- 记录:phone_number(varchar),provider_id(外键
提供商)
- routing_domain:provider_id(提供商的外键),domain_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 |
+----+--------+-----------+-------------+
现在,
- 给定 phone_number '39320xxxxxxx' 和 provider_id 9,我需要得到
domain_id=2;
- 给定 phone_number '39321xxxxxxx' 和 provider_id 9,我需要得到
domain_id=4;
因此,给定 phone_number '3932xxxxxxxx' 和 provider_id=9,我需要进行一些最佳匹配搜索。从 6 个字符开始搜索前缀,如果不匹配,尝试使用 5 个字符,依此类推,直到 3 个字符(393)。
我设法从 phone_number 仅从前缀到 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';
做这个最佳匹配有什么建议吗?
非常感谢!
Update
我试过这个:
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';
现在,如果我搜索“39325xxxxxxx”,则会找到前缀为“3932”的匹配项,
但是如果我搜索“39320xxxxxxx”,两个前缀都会匹配并且搜索 returns 2 行。
一个选项是有一个子查询,为您提供匹配 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, '%')
)
看我的 fiddle here.
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/#!9/2e36df/17
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
这就是我的设想。 我有 4 个表:记录、提供者、routing_domain、域。
- 域:id、名称(类似于 'example.com')
- 提供者:id、名称(类似于 'TLC')
- 记录:phone_number(varchar),provider_id(外键 提供商)
- routing_domain:provider_id(提供商的外键),domain_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 |
+----+--------+-----------+-------------+
现在,
- 给定 phone_number '39320xxxxxxx' 和 provider_id 9,我需要得到 domain_id=2;
- 给定 phone_number '39321xxxxxxx' 和 provider_id 9,我需要得到 domain_id=4;
因此,给定 phone_number '3932xxxxxxxx' 和 provider_id=9,我需要进行一些最佳匹配搜索。从 6 个字符开始搜索前缀,如果不匹配,尝试使用 5 个字符,依此类推,直到 3 个字符(393)。
我设法从 phone_number 仅从前缀到 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';
做这个最佳匹配有什么建议吗? 非常感谢!
Update
我试过这个:
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';
现在,如果我搜索“39325xxxxxxx”,则会找到前缀为“3932”的匹配项, 但是如果我搜索“39320xxxxxxx”,两个前缀都会匹配并且搜索 returns 2 行。
一个选项是有一个子查询,为您提供匹配 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, '%')
)
看我的 fiddle here.
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/#!9/2e36df/17
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