从 MySQL 中的分层数据生成基于深度的树(无 CTE)
嗨,很多天我一直在 MySQL 中解决这个问题,但是我无法弄清楚。你们有什么建议吗?
基本上,我有一个类别表,其中包含以下域:id
、name
(类别名称)和parent
(类别父级的 ID) )。
示例数据:
1 Fruit 0
2 Apple 1
3 pear 1
4 FujiApple 2
5 AusApple 2
6 SydneyAPPLE 5
....
有很多级别,可能超过 3 个级别。我想创建一个 sql 查询,根据层次结构对数据进行分组:parent >孩子>孙子>等等。
它应该输出树结构,如下所示:
1 Fruit 0
^ 2 Apple 1
^ 4 FujiApple 2
- 5 AusApple 2
^ 6 SydneyApple 5
- 3 pear 1
Can I do this using a single SQL query?我尝试过并且确实有效的替代方案如下:
SELECT * FROM category WHERE parent=0
在此之后,我再次循环数据,并选择parent = id的行。这似乎是一个糟糕的解决方案。因为是mySQL,所以不能使用CTE。
Hi For many days I have been working on this problem in MySQL, however I can not figure it out. Do any of you have suggestions?
Basically, I have a category table with domains like: id
, name
(name of category), and parent
(id of parent of the category).
Example Data:
1 Fruit 0
2 Apple 1
3 pear 1
4 FujiApple 2
5 AusApple 2
6 SydneyAPPLE 5
....
There are many levels, possibly more than 3 levels. I want to create an sql query that groups the datas according to he hierarchy: parent > child > grandchild > etc.
It should output the tree structure, as follows:
1 Fruit 0
^ 2 Apple 1
^ 4 FujiApple 2
- 5 AusApple 2
^ 6 SydneyApple 5
- 3 pear 1
Can I do this using a single SQL query? The alternative, which I tried and does work, is the following:
SELECT * FROM category WHERE parent=0
After this, I loop through the data again, and select the rows where parent=id. This seems like a bad solution. Because it is mySQL, CTEs cannot be used.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
如果您使用存储过程,您可以在从 php 到 mysql 的单个调用中完成此操作:
调用示例
希望这有帮助:)
完整脚本
测试表结构:
测试数据:
过程:
测试运行:
使用 Yahoo geoplanet 放置数据的一些性能
测试表中有 560 万行(位置),让我们看看从 php 调用的邻接列表实现/存储过程如何处理它。
总的来说,我对这些冷运行时非常满意,因为我什至不会开始考虑将数万行数据返回到我的前端,而是宁愿动态构建树,每次调用仅获取几个级别。哦,以防万一您认为 innodb 比 myisam 慢 - 我测试的 myisam 实现在所有方面都慢两倍。
更多内容在这里:http://pastie.org/1672733
希望这有帮助:)
You can do it in a single call from php to mysql if you use a stored procedure:
Example calls
Hope this helps :)
Full script
Test table structure:
Test data:
Procedure:
Test runs:
Some performance testing using Yahoo geoplanet places data
so that's 5.6 million rows (places) in the table let's see how the adjacency list implementation/stored procedure called from php handles that.
Overall i'm pretty pleased with those cold runtimes as I wouldn't even begin to consider returning tens of thousands of rows of data to my front end but would rather build the tree dynamically fetching only several levels per call. Oh and just incase you were thinking innodb is slower than myisam - the myisam implementation I tested was twice as slow in all counts.
More stuff here : http://pastie.org/1672733
Hope this helps :)
在 RDBMS 中存储分层数据有两种常见方法:邻接表(您正在使用)和嵌套集。 管理 MySQL 中的分层数据<中有一篇关于这些替代方案的非常好的文章/a>.您只能使用嵌套集模型在单个查询中执行您想要的操作。然而,嵌套集合模型使得更新层次结构的工作量更大,因此您需要根据您的操作需求进行权衡。
There are two common ways of storing hierarchical data in an RDBMS: adjacency lists (which you are using) and nested sets. There is a very good write-up about these alternatives in Managing Hierarchical Data in MySQL. You can only do what you want in a single query with the nested set model. However, the nested set model makes it more work to update the hierarchical structure, so you need to consider the trade-offs depending on your operational requirements.
您无法使用单个查询来实现此目的。在这种情况下,您的分层数据模型是无效的。我建议您尝试其他两种在数据库中存储分层数据的方法:MPTT 模型或“lineage”模型。使用这些模型中的任何一个都可以让您一次性完成所需的选择。
这是一篇包含更多详细信息的文章: http://articles.sitepoint.com/article/hierarchical -数据数据库
You can't achieve this using a single query. Your hierarchical data model is ineffective in this case. I suggest you try two other ways of storing hierarchical data in a database: the MPTT model or the "lineage" model. Using either of those models allows you to do the select you want in a single go.
Here is an article with further details: http://articles.sitepoint.com/article/hierarchical-data-database
线性方式:
我使用一个丑陋的函数在简单的字符串字段中创建一棵树。
该表可用于通过简单的 SQL 查询来选择树顺序中的所有行:
select * from morum_messages where m_topic=1234 order by m_linear asc
INSERT
只是选择父线性(和子线性)并根据需要计算字符串。DELETE
很简单,就是删除消息,或者线性删除父消息的所有回复。The linear way:
I am using a ugly function to create a tree in a simple string field.
the table can be used to select all the rows in the tree order with a simple SQL Query:
select * from morum_messages where m_topic=1234 order by m_linear asc
INSERT
is just select the parent linear (and children) and calculate the string as needed.DELETE
is simple as delete the message, or delete by linear all replies of the parent one.