将数据库结果转为数组
我刚刚为组织查询分层数据的“闭包表”方式制作了更新/添加/删除部分,如本幻灯片第 70 页所示: http://www.slideshare.net/billkarwin/sql-antipatterns-strike-back
我的数据库如下所示:
表类别:
ID Name
1 Top value
2 Sub value1
表 CategoryTree:
child parent level
1 1 0
2 2 0
2 1 1
但是,我在从单个查询中将完整树作为多维数组返回时遇到了一些问题。
这是我想要返回的内容:
array (
'topvalue' = array (
'Subvalue',
'Subvalue2',
'Subvalue3)
);
);
更新: 找到了这个链接,但我仍然很难将其转换为数组: http://karwin.blogspot.com/2010/ 03/rendering-trees-with-closure-tables.html
更新2: 我现在能够为每个类别添加深度,如果这有任何帮助的话。
I have just made the update/add/delete part for the "Closure table" way of organizing query hierarchical data that are shown on page 70 in this slideshare: http://www.slideshare.net/billkarwin/sql-antipatterns-strike-back
My database looks like this:
Table Categories:
ID Name
1 Top value
2 Sub value1
Table CategoryTree:
child parent level
1 1 0
2 2 0
2 1 1
However, I have a bit of an issue getting the full tree back as an multidimensional array from a single query.
Here's what I would like to get back:
array (
'topvalue' = array (
'Subvalue',
'Subvalue2',
'Subvalue3)
);
);
Update:
Found this link, but I still have a hard time to convert it into an array:
http://karwin.blogspot.com/2010/03/rendering-trees-with-closure-tables.html
Update2 :
I was able to add depths to each of the categories now, if that can be of any help.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
好的,我已经编写了扩展 Zend Framework DB 表、行和行集类的 PHP 类。无论如何,我一直在开发这个,因为几周后我将在 PHP Tek-X 上谈论分层数据模型。
我不想将我的所有代码发布到 Stack Overflow,因为如果我这样做,它们就会隐式获得知识共享许可。 更新:我将代码提交到Zend Framework extras 孵化器< /a> 我的演讲是使用 SQL 和 PHP 的分层数据模型在幻灯片共享。
我将用伪代码描述解决方案。我使用动物分类学作为测试数据,从 ITIS.gov 下载。该表是
longnames
:我为分类层次结构中的路径创建了一个闭包表:
给定一个节点的主键,您可以获取它的所有后代方式:
与闭包 AS p 的连接是包含每个节点的父 id。
该查询很好地利用了索引:
鉴于我在
longnames
中有 490,032 行,在closure
中有 4,299,883 行,它运行得非常好:现在我进行后处理上面 SQL 查询的结果,根据层次结构将行排序为子集(伪代码):
我还为 Rows 和 Rowsets 定义了类。 Rowset 基本上是一个行数组。 Row 包含行数据的关联数组,还包含其子项的 Rowset。叶节点的子行集为空。
行和行集还定义了名为 toArrayDeep() 的方法,该方法将其数据内容递归地转储为普通数组。
然后我可以像这样一起使用整个系统:
输出如下:
回复您关于计算深度或每条路径的实际长度的评论。
假设您刚刚将一个新节点插入到保存实际节点的表中(上例中的
长名称
),则新节点的 ID 由LAST_INSERT_ID()
在 MySQL 中,否则你可以通过某种方式得到它。Okay, I've written PHP classes that extend the Zend Framework DB table, row, and rowset classes. I've been developing this anyway because I'm speaking at PHP Tek-X in a couple of weeks about hierarchical data models.
I don't want to post all my code to Stack Overflow because they implicitly get licensed under Creative Commons if I do that. update: I committed my code to the Zend Framework extras incubator and my presentation is Models for Hierarchical Data with SQL and PHP at slideshare.
I'll describe the solution in pseudocode. I'm using zoological taxonomy as test data, downloaded from ITIS.gov. The table is
longnames
:I've created a closure table for the paths in the hierarchy of taxonomy:
Given the primary key of one node, you can get all its descendants this way:
The join to
closure AS p
is to include each node's parent id.The query makes pretty good use of indexes:
And given that I have 490,032 rows in
longnames
and 4,299,883 rows inclosure
, it runs in pretty good time:Now I post-process the result of the SQL query above, sorting the rows into subsets according to the hierarchy (pseudocode):
I also define classes for Rows and Rowsets. A Rowset is basically an array of rows. A Row contains an associative array of row data, and also contains a Rowset for its children. The children Rowset for a leaf node is empty.
Rows and Rowsets also define methods called
toArrayDeep()
which dump their data content recursively as a plain array.Then I can use the whole system together like this:
The output is as follows:
Re your comment about calculating depth -- or really length of each path.
Assuming you've just inserted a new node to your table that holds the actual nodes (
longnames
in the example above), the id of the new node is returned byLAST_INSERT_ID()
in MySQL or else you can get it somehow.建议的解决方案
下面的示例提供的内容比您要求的要多一些,但这是一种非常好的方法,并且仍然演示了每个阶段的信息来自何处。
它使用以下表结构:
这里是:
测试用例
在我的数据库中,我有以下行:
因此脚本输出以下(冗长)信息:
示例用法
如果您是,我建议创建某种递归函数将根据数据创建菜单:
这将输出以下内容:
享受
Proposed Solution
This following example gives a little more than you ask for, but it's a really nice way of doing it and still demonstrates where the information comes from at each stage.
It uses the following table structure:
Here it is:
Test Case
In my database I have the following rows:
And thus the script outputs the following (lengthy) information:
Example Usage
I'd suggest creating some kind of recursive function if you're going to create menus from the data:
which would output the following:
Enjoy
我喜欢 icio 的答案,但我更喜欢数组的数组,而不是对象的数组。这是他的脚本,经过修改后可以在不创建对象的情况下工作:
我认为公平地说,我的回答和 icios 都没有直接解决您的问题。它们都依赖于主表中的父 id 链接,并且不使用闭包表。但是,递归查询数据库绝对是可行的方法,但不是递归传递父 id,而是必须传递父 id 和深度级别(每次递归应增加 1),以便查询每个级别都可以使用父级+深度从闭包表中获取直接父级信息,而不是将其放在主表中。
哈特哈,
-FT
I loved the answer from icio, but I prefer to have arrays of arrays, rather than arrays of objects. Here is his script modified to work without making objects:
I think it fair to note that both my answer, and icios do not address your question directly. They both rely on having a parent id link in the main table, and make no use of the closure table. However, recursively querying the database is definitely the way to do, but instead of recursively passing the parent id, you have to pass in the parent id AND the level of the depth (which should increase by one on each recursion) so that the queries at each level can use parent + depth to get the direct parent information from the closure table rather than having it in the main table.
HTH,
-FT
当您希望输出为无序列表时,您可以按如下方式更改 outputCategories 方法(基于数组中的 ftrotters 数组):
When you want the output as a unordered list you can change the outputCategories method as follows (based on ftrotters arrays in arrays):
抱歉,但我认为您无法从(或任何)数据库查询中获取多维数组。
Sorry but I don't think you can't get a multi-dimensional array out of your (or any) database query.