我问了这个问题previously,但这是一个双层树,我得到的解决方案完美无缺。
我现在有一个多级树(最多3个,但我们假设将来会有更多。
我的代码目前看起来像这样:
SELECT * FROM fin_document AS finl
LEFT OUTER JOIN fin_document AS finl2
ON finl2.id = finl.parent_line_id
ORDER BY
CASE WHEN finl2.ordinal IS NULL THEN finl.ordinal
ELSE concat(finl2.ordinal,'-',finl.ordinal) END
让我们假设一个与以前类似的树:
(id) (Item) (#) (parent_line_id)
1234 - Car - 1 - null
0000 - Boat - 2 - null
2222 - House - 4 - null
6545 - Bike - 5 - null
6547 - Wheels - 0 - 1234
4442 - Bed - 1 - 2222
1474 - Sink - 0 - 2222
9456 - Tires - 0 - 6547 *New item, child of wheels
8975 - L.Nuts - 1 - 6547 *New item, child of wheels
哦,#列是"序数"
那么如何让这个与多个父母一起排序?
正确的排序应如下所示:
(id) (Item) (#) (parent_line_id)
1234 - Car - 1 - null
6547 - Wheels - 0 - 1234
9456 - Tires - 0 - 6547
8975 - L.Nuts - 1 - 6547
0000 - Boat - 2 - null
2222 - House - 4 - null
1474 - Sink - 0 - 2222
4442 - Bed - 1 - 2222
6545 - Bike - 5 - null
注意:我不能改变任何表格。我只能从表中提取数据,因为表是由另一家公司管理的,我们使用的软件是谁。我知道如果有更多的孩子,他们会变得越来越复杂,但我认为我的公司将使用这个孩子的人数不会超过3-4个。不幸的是,由于这种复杂性,这就是为什么我不得不回到这里并再次询问:(
答案 0 :(得分:1)
希望您不会在没有修改的情况下寻找适合N深层次结构的东西。
然而,这应该是相当简单的。
SELECT id,
item,
o,
parent_line_id
FROM (
SELECT *,
1 AS parentage,
o AS rank
FROM table1
WHERE parent_line_id IS NULL
UNION ALL
SELECT t2.id,
t1.item,
t1.o,
t1.parent_line_id,
2 AS parentage,
t2.o AS rank
FROM table1 t1
INNER JOIN table1 t2 ON t1.parent_line_id = t2.id
AND t2.parent_line_id IS NULL
UNION ALL
SELECT t3.id,
t1.item,
t1.o,
t1.parent_line_id,
3 AS parentage,
t3.o AS rank
FROM table1 t1
INNER JOIN table1 t2 ON t1.parent_line_id = t2.id
AND t2.parent_line_id IS NOT NULL
INNER JOIN table1 t3 ON t2.parent_line_id = t3.id
) q
ORDER BY rank ASC,
parentage ASC,
o ASC;
基本前提是我们识别所有无父项目,并为其提供1的父母身份。
然后我们确定他们的孩子,给他们2的父母,他们的孩子得到3的父母。
然后,所有这些都继承了第一个父母序号以进行分类。
可能有其他方法可以做到这一点,我甚至可能会去寻找它们,但同时也是如此 - 这很有效。
答案 1 :(得分:0)
这里有dirty trick来处理任意深度:
SELECT a.k, b.*
FROM (
SELECT a.id, a.k
FROM (
SELECT CONCAT(LEFT(
(@c := @previous_id <> b.id OR @previous_id IS NULL)
& (@id := IF( @c, b.id, (SELECT parent_line_id FROM fin_document WHERE id = @id)))
& (@num := LPAD(IF( @c, b.num, (SELECT num FROM fin_document WHERE id = @id)), 5, ' '))
& (@key := IF( @c, @num, CONCAT(@num, '', @key) ))
& (@previous_id := b.id),0),@key) k,
b.id
FROM fin_document a
STRAIGHT_JOIN ( SELECT @previous_id := NULL, id, num FROM fin_document ) b ) a
WHERE k IS NOT NULL
ORDER BY id, LENGTH(k) DESC) a
JOIN fin_document b ON a.id = b.id
GROUP BY a.id
ORDER BY k;
fiddle(不确定为什么列k没有正确显示。列k表示排序键,并且使用与原始查询类似的格式构建) 此外,它需要指数执行时间。所以它可能不是你想要的。
答案 2 :(得分:0)
**
**
对于正在搜索的任何人,如果您具有邻接列表ID->父结构,则实际上可以使用路径枚举模型来维护基于级别的排序:)
在“数据”表中,您将具有父级和一个排序值列
为了生成具有正确排序的层次结构,我使用以下CTE:
CTE_Topic_Details AS
(
SELECT Topic_id, CONVERT(Topic_id, CHAR(100)) as path, Topic_name as TopFullN,CONVERT(Topic_sort, CHAR(100)) as SortGPS
FROM topic
WHERE Topic_Topic_id IS NULL
UNION ALL
SELECT e.Topic_id, CONCAT(d.path, ".", CONVERT(e.Topic_id, CHAR(20))), CONCAT(d.TopFullN, ">", e.Topic_name), CONCAT(d.SortGPS, ".", CONVERT(e.Topic_sort, CHAR(20)))
FROM topic e
JOIN CTE_Topic_Details d ON e.Topic_Topic_id = d.Topic_id
)
很好,不是吗!