此图片展示了我正在努力实现的目标。左边是表格数据,右边是我正在尝试创建的表格。
该表使用parentID引用同一表中的另一个项来创建层次结构。
我将如何以这种方式创建查询并进行组织?
如果我选择“海盗”并希望得到所有父母,该怎么办?在我到达顶部之前,CFML中是否有任何东西比循环查询更容易?
答案 0 :(得分:2)
您的分层数据使用称为adjacency list的方法表示。 There are a number of other options,您最终使用的取决于数据更改的频率以及您正在使用的基础数据库 - 其中一些具有便于查询邻接列表的功能 - 其中主要是Common Table Expressions(CTE)。请参阅与其他数据库相关的问题。
Using a CTE you can retrieve a hierarchy from an adjacency list in order and calculate the "level" of each entry - 在您的情况下正确缩进。如果您的数据库没有CTE并且没有其他方法可以轻松查询它,请考虑使用不同的方法,nested sets可能是最容易访问的,其中检索速度快但却以更复杂的更改算法为代价(即插入,删除,移动)。
答案 1 :(得分:1)
我没有测试过这个......:)
<!--- item.cfc --->
<cfcomponent persistent="true" cache="read-only">
<cfproperty name="id" fieldtype="id">
<cfproperty name="parent"
fieldtype="many-to-one" cfc="item" fkcolumn="ParentID">
<cfproperty name="children" type="array"
fieldtype="one-to-many" cfc="item" fkcolumn="ParentID" inverse="true">
</cfcomponent>
<!--- display.cfm --->
<cffunction name="printItem" output="true">
<cfargument name="item" required="true">
<table>
<tr>
<td>#item.getName()#
<cfif item.hasChildren()>
<table>
<cfloop array="#item.getChildren()#" index="local.i">
<tr>
<td>#printItem(local.i)#
</cfloop>
</table>
</cfif>
</table>
</cffunction>
<cfset printItem( entityLoadByPK("item",1) )>
答案 2 :(得分:0)
我在考虑类似需求时考虑过的一种方法是异步构建层次结构 - 即使用AJAX请求。根据您的需要,这可能适用于您,也可能不适合您,但想象一下,不是立即构建整个树,而是最初只向用户显示顶级。然后,当用户选择顶级项目之一时,进行AJAX请求以查找所选项目的子项。根据需要重复每个孩子构建树。通过这种方式,问题非常简单,用于实现它的查询和代码也非常简单。
答案 3 :(得分:0)
这是我在你的帮助下想出来的。
<!--- adjacency list display --->
<cffunction name="adjacentList" output="true">
<cfargument name="alQuery" required="true">
<cfargument name="qid" required="false" default="0">
<cfquery name="alSubQuery" dbtype="query">
SELECT * FROM alQuery WHERE parentID=#qid#
</cfquery>
<cfif alSubQuery.RecordCount neq 0>
<ul>
<cfloop query="alSubQuery">
<li>
#name#
#adjacentList(#alQuery#,#id#)#
</li>
</cfloop>
</ul>
</cfif>
</cffunction>
使用:#adjacentList(#query#)#