这似乎是我想做的一项非常常见的任务,但我无法围绕 cfloops 和 cfqueries。
我有一个充满照片库的数据库。他们都有一个 ID 和一个 ParentID(除了根画廊 - 他们的 ParentID 是空白的),他们可以深入多个级别。这是画廊结构的示例:
- 1
- 1-1
- 1-2
- 2
- 2-1
- 2-1-1
- 2-1-2
- 2-2
- 2-1
我想自动将上面的这个结构输出到嵌套的 ul 和 li 中(就像上面一样)。这是怎么做的?我无法围绕 ul 和 li 的位置来正确显示层次结构级别。
这似乎是我想做的一项非常常见的任务,但我无法围绕 cfloops 和 cfqueries。
我有一个充满照片库的数据库。他们都有一个 ID 和一个 ParentID(除了根画廊 - 他们的 ParentID 是空白的),他们可以深入多个级别。这是画廊结构的示例:
我想自动将上面的这个结构输出到嵌套的 ul 和 li 中(就像上面一样)。这是怎么做的?我无法围绕 ul 和 li 的位置来正确显示层次结构级别。
这是 SQL 和 Coldfusion 的混合。在 SQL Server 中格式化标签可能不是最好的,但它确实提供了所需的格式。
SQL:
CREATE TABLE testTable(id int, parentID int)
INSERT INTO testTable(id, parentID) VALUES
(1, NULL)
, (2, 1)
, (3, 1)
, (4, NULL)
, (5, 4)
, (6, 5)
, (7, 5)
, (8, 4)
冷融合:
<cfscript>
qs = new query();
qs.setDatasource("datasource");
qs.setSQL("
;WITH cte AS
(
SELECT t.ID, t.parentID, 1 AS level,
CAST(DENSE_RANK() OVER (PARTITION BY t.parentID ORDER BY t.ID) AS varchar(max)) AS label
FROM testTable t
WHERE parentID IS NULL
UNION ALL
SELECT t.ID, t.parentID, cte.level + 1 AS level,
CAST(cte.label AS varchar(max)) + ' - ' + CAST(DENSE_RANK() OVER (PARTITION BY t.parentID ORDER BY t.ID) AS varchar(max)) AS label
FROM testTable t
INNER JOIN cte ON cte.ID = t.parentID
)
SELECT *,
DENSE_RANK() OVER (PARTITION BY parentID ORDER BY ID) AS [order]
FROM cte
ORDER BY label
");
qMenu = qs.execute().getResult();
oldLevel = 0;
for (i=1;i<=qMenu.recordCount;i++){
if (qMenu.level[i] > oldLevel) {
WriteOutput("<ul>");
}
while (qMenu.level[i] < oldLevel) {
WriteOutput("</ul>");
oldLevel--;
}
WriteOutput("<li>" & qMenu.label[i] & "</li>");
oldLevel = qMenu.level[i];
}
do {
WriteOutput("</ul>");
oldLevel--;
} while (oldLevel > 0);
</cfscript>
我将使用查询查询递归地执行此操作。
注意:以下代码未经测试,因此请以伪代码为例。
<cfquery query="qReadAllData">
select * from your_table
</cfquery>
<!--- Read all roots (no parent ID) --->
<cfquery query="qReadRoots" dbtype="query">
select nodeID from qReadAllData
where parentID is null
</cfquery>
<ul>
<cfloop query="qReadRoots">
<cfset processNode(qReadRoots.nodeID) />
</cfloop>
</ul>
<cffunction name="processNode" output="true">
<cfargument name="nodeID" type="any" />
<!--- Check for any nodes that have *this* node as a parent --->
<cfquery query="LOCAL.qFindChildren" dbtype="query">
select nodeID from qReadAllData
where parentID = #ARGUMENTS.nodeID#
</cfquery>
<cfif LOCAL.qFindChildren.recordcount>
<!--- We have another list! --->
<li>
<ul>
<!--- We have children, so process these first --->
<cfloop query="LOCAL.qFindChildren">
<!--- Recursively call function --->
<cfset processNode(LOCAL.qFindChildren.nodeID) />
</cfloop>
</ul>
<li>
<cfelse>
<!--- We have no more children, so we just output the value --->
<li>#nodeID#<li>
</cfif>
</cffunction>
晚了。我累了。我希望这是正确的:)
我想最简单的解决方案是使用 Query of Query ...
如果数据集很大,<cftree>
请尝试按需填充叶子。
给你,如果你给出实际的数据结构,我会改变以匹配你的实际字段:
您可以向表中添加深度和沿袭(fullPath)列,然后您只需执行一个简单的选择即可获取层次结构并相应地输出它。一个查询,完成。
WHILE EXISTS (SELECT * FROM Tree WHERE levelDeep Is Null)
UPDATE T SET T.levelDeep = P.levelDeep + 1,
T.fullPath= P.fullPath+ Ltrim(Str(T.ParentNode,6,0)) + '/'
FROM Tree AS T
INNER JOIN Tree AS P ON (T.ParentNode=P.Node)
WHERE P.levelDeep >=0
AND P.fullPathIs Not Null
AND T.levelDeep Is Null