@H_403_1@对于类似遗留票证的系统,我有以下简化的数据库表结构.
@H_403_1@
– 嗨,我有问题
– 问题仍然存在
– 没关系,我明白了
– 问题又回来了
– 再次出现同样的问题 @H_403_1@我只能想到一个循环和几个SQL查询执行,每个父和子,看起来像一个代码气味. @H_403_1@UPDATE @H_403_1@如Daan所述,这个问题似乎与How to create a MySQL hierarchical recursive query重复. @H_403_1@我决定不删除它,因为Ravan刚刚用Laravel方法回答了它,这有助于我解决问题,所以我将把它留在这里以备将来参考.
messages
id INT
parent_id INT
content TEXT
answer TEXT
...
@H_403_1@在列表中,我显示所有消息.单击消息时,我会显示其答案等.
@H_403_1@问题是:现在我需要一个与此消息相关的所有父项和子项的列表结构,以及此消息在树中的位置.我怎样才能从数据库中检索它们?
@H_403_1@我正在使用Laravel,但原始sql也可以帮助我找到方向.
@H_403_1@例:
@H_403_1@
╔════╦═══════════╦════════════════════════╦═════════════════╗ ║ id ║ parent_id ║ content ║ answer ║ ╠════╬═══════════╬════════════════════════╬═════════════════╣ ║ 1 ║ NULL ║ Hi,I have a problem ║ I can't help ║ ║ 2 ║ 1 ║ The problem persists ║ Ok,what is it? ║ ║ 3 ║ 2 ║ Nevermind,I got this ║ Oh,well. ║ ║ 4 ║ 3 ║ Problem is back ║ Which problem? ║ ║ 5 ║ 4 ║ The same problem again ║ ... ║ ╚════╩═══════════╩════════════════════════╩═════════════════╝@H_403_1@当显示id = 4的消息时,我应该能够显示如下列表: @H_403_1@消息历史:
– 嗨,我有问题
– 问题仍然存在
– 没关系,我明白了
– 问题又回来了
– 再次出现同样的问题 @H_403_1@我只能想到一个循环和几个SQL查询执行,每个父和子,看起来像一个代码气味. @H_403_1@UPDATE @H_403_1@如Daan所述,这个问题似乎与How to create a MySQL hierarchical recursive query重复. @H_403_1@我决定不删除它,因为Ravan刚刚用Laravel方法回答了它,这有助于我解决问题,所以我将把它留在这里以备将来参考.
最佳答案
由于您正在进行分层操作,因此应使用策略从数据库中保存和检索此数据.
@H_403_1@一种方法是使用Nested Set Model,这可以使它更容易.
Laravel有一个很好的解决方案,称为etrepat/baum,它也解释了它是如何工作的,我引用: @H_403_1@背后的理论,一个TL; DR版本 @H_403_1@可视化嵌套集如何工作的简单方法是考虑围绕所有嵌套集的父实体
它的孩子,它的父母围绕着它等等.所以这棵树: @H_403_1@
看起来像这样: @H_403_1@
普通的树突然很快.漂亮,不是吗?
原文链接:https://www.f2er.com/mysql/433220.htmlLaravel有一个很好的解决方案,称为etrepat/baum,它也解释了它是如何工作的,我引用: @H_403_1@背后的理论,一个TL; DR版本 @H_403_1@可视化嵌套集如何工作的简单方法是考虑围绕所有嵌套集的父实体
它的孩子,它的父母围绕着它等等.所以这棵树: @H_403_1@
root
|_ Child 1
|_ Child 1.1
|_ Child 1.2
|_ Child 2
|_ Child 2.1
|_ Child 2.2
@H_403_1@可以像这样可视化:
@H_403_1@
___________________________________________________________________
| Root |
| ____________________________ ____________________________ |
| | Child 1 | | Child 2 | |
| | __________ _________ | | __________ _________ | |
| | | C 1.1 | | C 1.2 | | | | C 2.1 | | C 2.2 | | |
1 2 3_________4 5________6 7 8 9_________10 11_______12 13 14
| |___________________________| |___________________________| |
|___________________________________________________________________|
@H_403_1@数字代表左右边界.然后表可能看起来像这样: @H_403_1@
id | parent_id | lft | rgt | depth | data
1 | | 1 | 14 | 0 | root
2 | 1 | 2 | 7 | 1 | Child 1
3 | 2 | 3 | 4 | 2 | Child 1.1
4 | 2 | 5 | 6 | 2 | Child 1.2
5 | 1 | 8 | 13 | 1 | Child 2
6 | 5 | 9 | 10 | 2 | Child 2.1
7 | 5 | 11 | 12 | 2 | Child 2.2
@H_403_1@要获得父节点的所有子节点,您
@H_403_1@
SELECT * WHERE lft IS BETWEEN parent.lft AND parent.rgt
@H_403_1@为了得到孩子的数量,这是
@H_403_1@
(right - left - 1)/2
@H_403_1@为了让一个节点及其所有祖先回到根节点,你
@H_403_1@
SELECT * WHERE node.lft IS BETWEEN lft AND rgt
@H_403_1@正如您所看到的那样,查询将是递归的并且过于缓慢普通的树突然很快.漂亮,不是吗?