2016-08-14 45 views
2

我有这样的一个表:MySQL的:选择最长的字符串出现在搜索字符串

id path 
1 /
2  /city/ 
3  /city/europe/ 
4  /city/north america/ 
6  /city/europe/germany/berlin/ 
7  /city/europe/germany/ 
8  /city/north america/usa/ 
[...] 

和这样的搜索字符串:

"/city/north america/usa/florida/miami/" 


我需要选择最长路径这就是搜索字符串,所以结果将是

id path 
8 /city/north america/usa/ 


表中存在任何路径的父节点。路径可以任意长。搜索字符串至少包含“/”。

我可以想到一些解决方案,比如在列上使用通配符,分割搜索字符串并使用IN或连接执行选择。

什么是最好和最快的方式来做到这一点?
可以用任何方式修改表格。


编辑: 与我想出迄今最快的解决方案:

SELECT * FROM table_name 
WHERE path IN ('/','/city/','/city/north america/', '/city/north america/usa/', '/city/north america/usa/florida/', '/city/north america/usa/florida/miami/') 
ORDER by LENGTH(path) DESC LIMIT 1; 

回答

0
SELECT * 
FROM table_name 
WHERE path REGEXP '^/city((((/north america)?/usa)?/florida)?/miami)?\/?$' 
ORDER BY LENGTH(path) DESC 
LIMIT 1 
+0

这不起作用。它返回所有列(并将其限制为一个结果,在这种情况下是错误的) – Megatron

+0

@Megatron在回答中编辑了'order by'部分 – mnv

+0

它可以工作,但它比这个长1000倍: 'SELECT * FROM table_name WHERE path IN('/','/ city /','/ city/north america /','/ city/north america/usa /','/ city/north america/usa/florida /','/city/north america/usa/florida/miami /')通过LENGTH(路径)DESC LIMIT 1命令' 但是,我认为这不是最好的解决方案。 – Megatron

0

或者,试试这个:

select * FROM tbl WHERE path= 
(select max(path) from tbl 
    where '/city/north america/usa/florida/miami/' like concat(path,'%') 
) 

(编辑) 那么也许这是更快:

select * from tbl where instr('/city/north america/usa/florida/miami/',path)=1 
order by path desc limit 1 
+0

单独的子查询就够了,但与WHERE IN select相比,它非常慢。 – Megatron

+0

第二个查询实际上有点慢。它必须将该功能应用于每一行。我相信我可以通过在数据中使用树结构来以某种方式使用B树索引。 如果有必要,我可以使用嵌套集,但这会使模型的管理更复杂一些。 – Megatron

+0

也许你的表有一些索引问题?我的[小提琴](http://sqlfiddle.com/#!9/f6bbd/6)84000条记录需要大约16ms才能完成。 – cars10m