如何在ColdFusion中为关系型数据库实现子任务判断与多子任务循环?
任务与子任务层级展示的最优实现方案
直接在循环里用<cfif taskID = sub-taskid>判断的方式,要么会触发多次数据库查询(性能差),要么要处理重复的主任务数据(逻辑繁琐)。最优思路是先把所有子任务按父任务ID结构化分组,再循环主任务时直接调用对应子任务列表。
步骤1:查询并分组子任务
一次性查询所有子任务,存入以主任务ID为键的结构中,后续循环主任务时可快速获取对应子任务,避免重复查库。
<!--- 查询所有子任务,按主任务ID排序 ---> <cfquery name="qSubTasks" datasource="你的数据源"> SELECT subTaskID, taskID, subTaskName, subTaskDesc FROM sub-task ORDER BY taskID, subTaskID </cfquery> <!--- 创建存储子任务的结构:key为主任务ID,value为该任务下的子任务查询集 ---> <cfset subTaskGroup = {}> <cfloop query="qSubTasks"> <!--- 若当前主任务ID未在结构中,初始化空查询集 ---> <cfif NOT structKeyExists(subTaskGroup, qSubTasks.taskID)> <cfset subTaskGroup[qSubTasks.taskID] = queryNew("subTaskID,taskID,subTaskName,subTaskDesc")> </cfif> <!--- 将当前子任务加入对应主任务的查询集 ---> <cfset queryAddRow(subTaskGroup[qSubTasks.taskID])> <cfset querySetCell(subTaskGroup[qSubTasks.taskID], "subTaskID", qSubTasks.subTaskID)> <cfset querySetCell(subTaskGroup[qSubTasks.taskID], "taskID", qSubTasks.taskID)> <cfset querySetCell(subTaskGroup[qSubTasks.taskID], "subTaskName", qSubTasks.subTaskName)> <cfset querySetCell(subTaskGroup[qSubTasks.taskID], "subTaskDesc", qSubTasks.subTaskDesc)> </cfloop>
步骤2:循环主任务并渲染子任务
查询所有主任务,循环时检查结构中是否存在当前任务的子任务,若存在则嵌套循环渲染子任务行。
<!--- 查询所有主任务 ---> <cfquery name="qTasks" datasource="你的数据源"> SELECT taskID, taskName, taskDesc FROM tasks ORDER BY taskID </cfquery> <!--- 渲染结果表格 ---> <table border="1" cellpadding="4"> <thead> <tr> <th>ID</th> <th>名称</th> <th>描述</th> <th>类型</th> </tr> </thead> <tbody> <cfloop query="qTasks"> <!--- 渲染主任务行 ---> <tr> <td>#qTasks.taskID#</td> <td>#qTasks.taskName#</td> <td>#qTasks.taskDesc#</td> <td>主任务</td> </tr> <!--- 检查是否有对应子任务,有则循环渲染 ---> <cfif structKeyExists(subTaskGroup, qTasks.taskID)> <cfloop query="subTaskGroup[qTasks.taskID]"> <tr style="background-color:#f5f5f5;"> <!--- 加缩进区分主/子任务 ---> <td> #subTaskID#</td> <td> [子任务] #subTaskName#</td> <td> #subTaskDesc#</td> <td>子任务</td> </tr> </cfloop> </cfif> </cfloop> </tbody> </table>
为什么这个方案更优?
- 性能更好:仅需2次数据库查询,避免了循环主任务时每次查子任务的N+1查询问题。
- 逻辑更清晰:主任务与子任务的渲染逻辑分离,不用处理重复的主任务数据。
- 扩展性强:后续修改子任务展示逻辑,只需调整子任务循环部分即可。
备选方案:联合查询去重渲染
如果不想用结构分组,也可以用主任务与子任务的左连接查询,通过判断主任务ID是否重复避免重复渲染主任务,但这种方式会返回重复的主任务数据,效率不如分组方案:
<cfquery name="qCombined" datasource="你的数据源"> SELECT t.taskID, t.taskName, t.taskDesc, st.subTaskID, st.subTaskName, st.subTaskDesc FROM tasks t LEFT JOIN sub-task st ON t.taskID = st.taskID ORDER BY t.taskID, st.subTaskID </cfquery> <table border="1" cellpadding="4"> <thead>...</thead> <tbody> <cfset lastTaskID = 0> <cfloop query="qCombined"> <!--- 仅当前主任务ID与上一个不同时,渲染主任务行 ---> <cfif qCombined.taskID NEQ lastTaskID> <tr> <td>#qCombined.taskID#</td> <td>#qCombined.taskName#</td> <td>#qCombined.taskDesc#</td> <td>主任务</td> </tr> <cfset lastTaskID = qCombined.taskID> </cfif> <!--- 子任务存在时渲染 ---> <cfif qCombined.subTaskID IS NOT NULL> <tr style="background-color:#f5f5f5;"> <td> #qCombined.subTaskID#</td> <td> [子任务] #qCombined.subTaskName#</td> <td> #qCombined.subTaskDesc#</td> <td>子任务</td> </tr> </cfif> </cfloop> </tbody> </table>
内容的提问来源于stack exchange,提问作者ArilVade
相关产品推荐
相关产品推荐

