Php mysql中基于路径的选择

Php mysql中基于路径的选择,php,mysql,sql,materialized-path-pattern,Php,Mysql,Sql,Materialized Path Pattern,我有一个列id、一个列父级和一个作为物化路径的列路径 看起来像 1 | \N | 1 2 | 1 | 1/2 3 | 2 | 1/2/3 4 | 3 | 1/2/3/4 5 | 3 | 1/2/3/5 6 | 2 | 1/2/6 7 | 6 | 1/2/6/7 8 | 2 | 1/2/8 9 | 1 | 1/9 10 | 9 | 1/9/10 11 | 10 | 1/9/10/11 12 | 11 | 1/9/10/

我有一个列id、一个列父级和一个作为物化路径的列路径

看起来像

1  | \N | 1  
2  | 1  | 1/2  
3  | 2  | 1/2/3  
4  | 3  | 1/2/3/4  
5  | 3  | 1/2/3/5  
6  | 2  | 1/2/6  
7  | 6  | 1/2/6/7  
8  | 2  | 1/2/8  
9  | 1  | 1/9  
10 | 9  | 1/9/10  
11 | 10 | 1/9/10/11  
12 | 11 | 1/9/10/11/12  
13 | 11 | 1/9/10/11/13  
14 | 11 | 1/9/10/11/14  
15 | 14 | 1/9/10/11/14/15  
16 | 14 | 1/9/10/11/14/16  
17 | 14 | 1/9/10/11/14/17  
18 | 10 | 1/9/10/18  
19 | \N | 19  
20 | 19 | 19\20  
21 | 19 | 19\21
我需要根据这个表进行一些查询

我需要做的查询是 选择id为9的所有子项

可以正常工作,直到您将ID替换为1或19,因为开始时没有/

SELECT * FROM `tester` WHERE 'path' LIKE '%1/%';
将选择数字以1结尾的所有行,因此,1、11、21、31、211等

SELECT * FROM `tester` WHERE 'path' LIKE '1/%';
将对第1行或第19行正常工作

因此,从tester中选择*path,如“1/%”或“%/1/%”等; 是我能想到的最好的,有什么建议吗

选择9的直接子级,但不选择子级 为此,选择*fromtesterwhere'parent'=9;会很好的

选择9的子级的聚合计数,x级深度

所以我想以一行level1,level2,level3。。。levelx或x行,表示不同的级别

在这个例子中,让我们假设x是3 这个例子中的行是9,8,6,如果我们要求它是3,那么它将是第4级

有什么想法吗

编辑

我再一次完全不知道该怎么做

编辑:


这些解决方案基于字符串比较,没有经过优化,不能使用索引。你应该考虑用不同的方式规范你的表格。看

关于一些问题:

选择id为9的所有子项:

由于Path列不包含前导斜杠和尾随斜杠,因此需要将它们连接到路径:

SELECT * 
FROM tester
WHERE CONCAT('/', path, '/') LIKE '%/9/%';
选择9的子级的合计计数,x级深度:

我们需要按路径中的斜线数减去父路径中的斜线数进行分组:

SELECT (LENGTH(c.Path) - LENGTH(REPLACE(c.Path, '/', '')))
    - (LENGTH(p.Path) - LENGTH(REPLACE(p.Path, '/', ''))) AS Level,
    COUNT(*)
FROM tester c
    JOIN tester p ON c.Parent = p.ID
WHERE CONCAT('/', path, '/') LIKE '%/9/%';
GROUP BY 1
为了简单起见,我使用上面的查询来显示所有级别,如果您想限制x个级别的深度,请使用下面查询中的WHERE谓词

选择9的子id向下至x级别,级别相对于9:

我们将路径列搜索到x个级别,同时考虑父级:

SELECT c.*
FROM tester c
    JOIN tester p ON c.Parent = p.ID
WHERE CONCAT(
    '/',
    SUBSTRING_INDEX(
        Path, 
        '/', 
        (LENGTH(p.Path) - LENGTH(REPLACE(p.Path, '/', ''))) + 4
    ),
'/') LIKE '%/9/%'
我们正在采取的步骤:

我们需要找出父级的深度,我们可以通过计算父级路径中的斜线来找到。LENGTHp.Path-LENGTHREPLACEp.Path“/”, 我们需要在这个数字上加1,因为带1斜杠的路径有2层深。 我们添加x个所需级别。 抓取路径列,直到总计级别,使用函数。 添加前导斜杠和尾随斜杠。 在最后一个字符串中搜索9。
你能更详细地解释你所说的9个孩子的总数是什么意思吗,x级深度?嗨,Scrum大师,为这些欢呼,根据你的评论,我的意思是,在每一级我想知道有多少个孩子居住,在这种情况下,孙子不被视为孩子。
#select all information, and relative level from parent of children of specific node(5) down to a maximum of three levels, do no include the parent
SELECT child.*, 
LENGTH(REPLACE(child.path, parent.path, '')) - LENGTH(REPLACE(REPLACE(child.path, parent.path, ''), '/', '')) AS LEVEL
FROM `tester` child JOIN `tester` parent ON child.path LIKE CONCAT(parent.path,'%') 
WHERE parent.id  =9 
GROUP BY id HAVING LEVEL <= 3 AND LEVEL > 0;
SELECT * 
FROM tester
WHERE CONCAT('/', path, '/') LIKE '%/9/%';
SELECT (LENGTH(c.Path) - LENGTH(REPLACE(c.Path, '/', '')))
    - (LENGTH(p.Path) - LENGTH(REPLACE(p.Path, '/', ''))) AS Level,
    COUNT(*)
FROM tester c
    JOIN tester p ON c.Parent = p.ID
WHERE CONCAT('/', path, '/') LIKE '%/9/%';
GROUP BY 1
SELECT c.*
FROM tester c
    JOIN tester p ON c.Parent = p.ID
WHERE CONCAT(
    '/',
    SUBSTRING_INDEX(
        Path, 
        '/', 
        (LENGTH(p.Path) - LENGTH(REPLACE(p.Path, '/', ''))) + 4
    ),
'/') LIKE '%/9/%'