gpt4 book ai didi

mysql - 没有存储过程的树层次查询

转载 作者:行者123 更新时间:2023-11-29 20:35:41 26 4
gpt4 key购买 nike

我使用的是MySQL,是否可以从下面的表结构中通过单个SQL语句获得以下结果?

目前,我可以通过在 PHP 代码中使用逻辑 while 循环来获得相同的结果。如果我能在单个 SQL 中实现,那么对于性能来说就很好了。

预期结果:

|----------+-----------------------------------------------+
| Id (PK) + headerANDsubheader +
|----------+-----------------------------------------------+
| 1 + A-head +
| 4 + -A-head-A1-subHead +
| 5 + -A-head-A2-subHead +
| 6 + --A-head-A1-subHead-A1.1-subHead +
| 7 + --A-head-A1-subHead-A1.2-subHead +

Id 是主键。如果父键为 0,则表示其根级别标题。

如果ParentKey不等于0,则表示它是某人的子标题,而ParentKey是该子标题的指针。

表:Header_sub

|----------+-----------------------------------------------+------------+
| Id (PK) + headerANDsubheader + ParentKey +
|----------+-----------------------------------------------+------------+
| 1 + A-head + 0 +
|----------+-----------------------------------------------+------------+
| 2 + B-head + 0 +
|----------+-----------------------------------------------+------------+
| 3 + C-head + 0 +
|----------+-----------------------------------------------+------------+
| 4 + A-head-A1-subHead + 1 +
|----------+-----------------------------------------------+------------+
| 5 + A-head-A2-subHead + 1 +
|----------+-----------------------------------------------+------------+
| 6 + A-head-A1-subHead-A1.1-subHead + 4 +
|----------+-----------------------------------------------+------------+
| 7 + A-head-A1-subHead-A1.2-subHead + 4 +
|----------+-----------------------------------------------+------------+

我正在尝试这样...

SELECT 
CONCAT(REPEAT(' ', (COUNT(parent.subject_group_name) - 1) ), node.subject_group_name) AS name
FROM
major_scholastic as node,
major_scholastic as parent
WHERE
node.s_gid BETWEEN parent.s_gid AND parent.parent_id
GROUP BY node.subject_group_name
ORDER BY node.s_gid

最佳答案

您的headerANDsubheader列是某种物化路径。这允许您通过使用带有 LIKE 条件的 JOIN 来获取所有祖先(不仅仅是直接父代)。

以下查询演示了如何获取不同任务可能需要的信息:

select node.*
, group_concat(anc.Id order by char_length(anc.headerANDsubheader)) as idPath
, group_concat(lpad(anc.Id, 10, 0) order by char_length(anc.headerANDsubheader)) as idPathSortable
, count(anc.Id) as depthLevel
, concat(repeat('- ', count(anc.Id)-1), node.headerANDsubheader) as indendtedHeader
from header_sub node
join header_sub anc
on node.headerANDsubheader like concat(anc.headerANDsubheader, '%')
group by node.Id
order by idPathSortable

结果如下所示:

| Id |             headerANDsubheader | ParentKey | idPath |                   idPathSortable | depthLevel |                    indendtedHeader |
|----|--------------------------------|-----------|--------|----------------------------------|------------|------------------------------------|
| 1 | A-head | 0 | 1 | 0000000001 | 1 | A-head |
| 4 | A-head-A1-subHead | 1 | 1,4 | 0000000001,0000000004 | 2 | - A-head-A1-subHead |
| 6 | A-head-A1-subHead-A1.1-subHead | 4 | 1,4,6 | 0000000001,0000000004,0000000006 | 3 | - - A-head-A1-subHead-A1.1-subHead |
| 7 | A-head-A1-subHead-A1.2-subHead | 4 | 1,4,7 | 0000000001,0000000004,0000000007 | 3 | - - A-head-A1-subHead-A1.2-subHead |
| 5 | A-head-A2-subHead | 1 | 1,5 | 0000000001,0000000005 | 2 | - A-head-A2-subHead |
| 2 | B-head | 0 | 2 | 0000000002 | 1 | B-head |
| 3 | C-head | 0 | 3 | 0000000003 | 1 | C-head |

sqlfiddle

现在只需迈出一小步即可获得您需要的结果:

select node.Id, concat(
repeat(' ', count(anc.Id)-1),
repeat('-', count(anc.Id)-1),
node.headerANDsubheader
) as indendtedHeader
from header_sub node
join header_sub anc
on node.headerANDsubheader like concat(anc.headerANDsubheader, '%')
group by node.Id
order by group_concat(lpad(anc.Id, 10, 0) order by char_length(anc.headerANDsubheader))

结果:

| Id |                    indendtedHeader |
|----|------------------------------------|
| 1 | A-head |
| 4 | -A-head-A1-subHead |
| 6 | --A-head-A1-subHead-A1.1-subHead |
| 7 | --A-head-A1-subHead-A1.2-subHead |
| 5 | -A-head-A2-subHead |
| 2 | B-head |
| 3 | C-head |

sqlfiddle

更新:

join header_sub anc
on node.headerANDsubheader like concat(anc.headerANDsubheader, '%')

anc 是“ancestor”的缩写。我们希望将每个节点与其所有祖先(包括其自身)连接起来。该条件可以理解为 anc.headerANDsubheader IS PREFIX OF node.headerANDsubheader。因此“A-head-A1-subHead-A1.1-subHead”将与“A-head”、“A-head-A1-subHead”和“A-head-A1-subHead-A1.1-subHead”连接”。通过 node.id 对结果进行分组,我们可以使用聚合 COUNT 来获取深度级别,并使用 GROUP_CONCAT 来生成有用的路径。不过,最好将深度和路径存储在表中,这样我们就根本不需要连接。

关于mysql - 没有存储过程的树层次查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38813091/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com