感谢上一个问题的Paul Spiegel's answer,我在数据库tab
中有一个表dab
,它由四列组成。一个简单的ID列(id
),它也是主键(int),pat
列(varchar(255)),path
列(varchar(191)) ,最后has_tree
(位(1))。
id pat path has_tree
1 AA 1 1
2 ABA 1/2 1
3 ABCA 1/3 1
4 ABA 1/5 0
5 AB 2 0
6 BBB 2/1 1
7 CAB 2/2 1
8 ABC 1/4 0
9 ABC 1/5/7 1
10 ABA 3/2 1
给定pat
值(如果存在),我想要
pat
值(包括输入' s,如果has_tree==1
),has_tree == 1
。因此输入AA应返回['AA', 'ABA', 'ABCA', 'ABC']
。
重要的评论是,输入path
的{{1}}不一定是单个项目的根路径,换句话说:它很可能是输入pat
类似于path
,在这种情况下,我希望1/12/45/966
是pat
的后代且其中{{1}的所有唯一path
值是1/12/45/966
。另一个注意事项是路径可能非常深,因此即使输入has_tree
为1
,结果也可能更深层次,例如path
。
Paul建议使用以下查询,该查询适用于建议的数据结构,但是您可以看到当前的结构和要求略有不同。 (另请注意,我有一个包含多个表的数据库。因此,在数据库1
中给出一个表1/22/36/88/98/455/878/1205/2555
我想执行该脚本。)
tab
我试图用PHP做这个,然后调用一些SQL数据库。 是否有可能以通用,高性能的形式编写它,以便它适用于PostgreSQL,MySQL(i)和其他?如果没有,我至少想看看MySQLi和PostgreSQL变体。
基于保罗上面的示例代码,我认为这将是这些内容,但我不确定。 我也不确定为什么dab
运算符是必要的以及它在此上下文中的作用(我知道它通常做什么,但不知道为什么在这种情况下有必要)。我确信这些代码可以改进,修复,并使所有SQL风格更通用?另外,我没有看到下面的尝试包括输出中的当前输入SELECT t.*
FROM tree t
CROSS JOIN tree r -- root
WHERE r.CELL = '3B0'
AND t.path LIKE CONCAT(r.path, '%');
。
JOIN
加分问题:我已将所有列编入索引,但pat
除外。将该列编入索引也是有益的吗?
答案 0 :(得分:1)
首先注意:路径应以反斜杠结尾('1/'
,'1/2/'
而不是'1'
和'1/2'
)。这很重要,否则您无法匹配子树的根。例如:
WHERE path LIKE '1/%'
与'1'
不匹配,但会与'1/'
匹配。
您也可以不跳过查询中的反斜杠:
WHERE path LIKE '1%'
将匹配根'1'
,但也会匹配'10..'
现在回答您的问题:如果您已经知道根节点的路径,那么您就不需要加入:
SELECT * FROM tab WHERE path LIKE '1/%' AND has_tree
只获得" unique"拍你可以使用DISTINCT
关键字:
SELECT DISTINCT pat
FROM tab
WHERE path LIKE '1/%'
AND has_tree
那就是它。
如果您不知道根路径但只知道pat
值,则需要运行两个查询(首先获取路径然后获取后代)或使用连接。
的PostgreSQL:
SELECT DISTINCT t.pat
FROM tab t
JOIN tab r ON t.path LIKE r.path || '%'
WHERE r.pat = 'AA' -- input
AND t.has_tree
演示:http://rextester.com/EXZT43019
MySQL的:
SELECT DISTINCT t.pat
FROM tab t
JOIN tab r ON t.path LIKE CONCAT(r.path, '%')
WHERE r.pat = 'AA' -- input
AND t.has_tree
演示:http://rextester.com/DNHRJ83456
注意:正如您将在domo中看到的,如果您使用以下命令更改模式,您还可以在MySQL中使用管道(||
)进行连接:
SET sql_mode=PIPES_AS_CONCAT;
关于索引:布尔列的索引通常不是很有用。但是,您只能确定是否测试它。对于给定的查询,(has_tree, path)
上的复合索引可能会提高性能。