【问题标题】:<cfoutput> With Many-To-Many Relationship<cfoutput> 具有多对多关系
【发布时间】:2021-01-14 17:12:44
【问题描述】:

我正在为我们的会计部门处理一个项目。我有一个带有分类帐代码的数据库(MySQL)表。我们公司有几个不同的办公地点,这些代码中的每一个都可以适用于一个或多个办公地点。每个办公地点可以有一个或多个适用的分类帐代码。因此,我与持有code_idlocation_id 的桥接表建立了多对多关系。我的SQL如下:

SELECT gl.`code_id`, gl.`account_code`, gl.`account_type`, gl.`account_desc`, glloc.`location_id`
FROM `gl_codes` as gl
    LEFT JOIN `gl_codes_locations` as glloc
ON gl.`code_id` = glloc.`code_id`
ORDER BY gl.`code_id`, glloc.`location_id`

这会生成一个表格,其中每个 code_id/location_id 对都有一个单独的行。我想使用cfoutput 在表格中显示它。我只希望每个code_id 有一行,但我将在每一行中使用一列来标记该代码是否适用于给定的location_id,如下所示:

| CodeAccount | CodeType | CodeDescription | Code Location | | | | | 1 | 2 | 3 | 4 | |SomeAcct | SomeCode | Some Desc | X | | X | |


我知道我不能用多个query 属性嵌套cfoutput 标签。我尝试了一些分组,但我似乎无法做到正确。请帮忙!

【问题讨论】:

  • 请编辑您的问题,以显示您对分组的尝试以及尝试时发生的情况。

标签: mysql coldfusion cfquery cfoutput


【解决方案1】:

这应该让您非常接近。首先我们需要一个可用 ID 的列表,这样我们就知道需要多少个 Location 子列。

<cfquery name="locationData">
  SELECT location_id FROM gl_codes_locations ORDER BY location_id
</cfquery>
<cfset allLocationIds = ValueList(locationData.location_id)>

然后,在表格内部,我们可以使用这些信息构建表头和正文:

<thead>
    <tr>
      <td>Code ID</td>
      <td>Code Account</td>
      <td>Code Type</td>
      <td>Code Description</td>
      <td colspan="#ListLen(allLocationIds)#">Code Location</td>
    </tr>
    <tr>
      <td></td>
      <td></td>
      <td></td>
      <td></td>
      <cfloop list="#allLocationIds#" index="id">
        <td>#HtmlEditFormat(id)#</td>
      </cfloop>
    </tr>
</thead>
<tbody>
  <cfoutput query="ledgerData" group="code_id">
    <cfset currLocationIds = "">
    <cfoutput>
      <cfset currLocationIds = ListAppend(currLocationIds, location_id)>
    </cfoutput>
    <tr>
      <td>#HtmlEditFormat(code_id)#</td>
      <td>#HtmlEditFormat(account_code)#</td>
      <td>#HtmlEditFormat(account_type)#</td>
      <td>#HtmlEditFormat(account_desc)#</td>
      <cfloop list="#allLocationIds#" index="id">
        <td>#ListFind(currLocationIds, id) gt 0 ? 'X' : ''#</td>
      </cfloop>
    </tr>
  </cfoutput>
</cfoutput>

【讨论】:

    【解决方案2】:

    感谢@Tomalac 和他的ValueList 建议,我能够根据我的代码调整它并让它按照我想要的方式工作。子栏提示很棒,我将来可能会实现它,但现在我们处理的是固定数量的位置。

    供参考,相关完整代码如下。出于隐私原因,我编辑了位置名称。

    <table class="table table-striped table-bordered">
        <thead class="bg-nav text-white">
            <tr>
                <th scope="col" rowspan="2" class="align-middle">Code</th>
                <th scope="col" rowspan="2" class="align-middle">Type</th>
                <th scope="col" rowspan="2" class="align-middle">Description</th>
                <th scope="col" colspan="4" class="text-center">Applies To</th>
                <th scope="col" rowspan="2" class="text-center align-middle">Edit</th>
                <th scope="col" rowspan="2" class="text-center align-middle">Delete</th>
            </tr>
            <tr>
                <th scope="col">Chicago</th>
                <th scope="col">Detroit</th>
                <th scope="col">LA</th>
                <th scope="col">New York</th>
            </tr>
        </thead>
        <tbody>
            <cfoutput query="codes" group="code_id">
                    <tr>
                        <!--- Use function in cfcomponent to grab the location(s) that pertain to the given code_id --->
                        <!--- Dump query results into ValueList --->
    <cfset codeLocations = ValueList(createObject("component", "com.modules.glcodes").getCodeLocations("query", codes.code_id).location_id)>
                        <td>#account_code#</td>
                        <td>#account_type#</td>
                        <td>#account_desc#</td>
                        <td><cfif ListLen(codeLocations) GT 0 AND (ListContains(codeLocations, "3") GT 0)>X</cfif></td>
                        <td><cfif ListLen(codeLocations) GT 0 AND (ListContains(codeLocations, "2") GT 0)>X</cfif></td>
                        <td><cfif ListLen(codeLocations) GT 0 AND (ListContains(codeLocations, "4") GT 0)>X</cfif></td>
                        <td><cfif ListLen(codeLocations) GT 0 AND (ListContains(codeLocations, "1") GT 0)>X</cfif></td>
                        <td>Edit</td>
                        <td>Delete</td>
                </tr>
            </cfoutput>
        </tbody>
    </table>
    

    【讨论】:

    • 如果可以避免,请不要在每个表行中访问数据库服务器一次。创建一个包含整个表的所有数据的查询。
    • @Tomalak 这是我没有想到的一个非常好的观点。执行“主”查询然后查询查询以创建 ValueList 会更好吗?
    • 任何避免访问数据库的方法都会提高页面性能。您已经将codes 查询按code_id 分组,所以像我一样使用内部&lt;cfoutput&gt;,您应该获得所需的ID。
    • &lt;cfoutput&gt; 不能嵌套,除非分组。分组时,内部&lt;cfoutput&gt; 在组中每个项目运行一次,而外部每个组运行一次​​。如果您知道的话,它的工作方式类似于 Crystal Reports 中的“组/组页眉/组详细信息/组页脚”机制。您可以通过这种方式设置多个级别的分组,但您始终需要预先对组字段进行排序,即当组字段的值发生变化时,ColdFusion 将启动一个新组。
    • 另外,使用 ListFind() / ListFindNoCase() - 而不是 ListContains。后者搜索子字符串,而不是 whole 值。 trycf.com/gist/27e4d8d276aed791c128986a56ba30c5/…
    猜你喜欢
    • 1970-01-01
    • 2021-09-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多