在循环中组合查询行

时间:2010-05-28 20:35:48

标签: coldfusion union cfquery

我有以下ColdFusion 9代码:

<cfloop from="1" to="#arrayLen(tagArray)#" index="i">
    <cfquery name="qryGetSPFAQs" datasource="#application.datasource#">
        EXEC searchFAQ '#tagArray[i]#'
    </cfquery>
</cfloop>

EXEC在数据库服务器上执行存储过程,该存储过程返回数据行,具体取决于参数。我想要做的是将查询合并到一个查询对象中。换句话说,如果它循环3次并且每个循环返回4行,我想要一个在一个对象中具有所有12行的查询对象。我如何实现这一目标?

3 个答案:

答案 0 :(得分:2)

您可能希望采用不同的方法(修改存储过程以接受多个参数或使用列表和fnSplit)并一次性返回数据集。但是,要直接回答您的问题,您可以按照以下要求组合查询:

您可以在查询查询中使用UNION来组合所有数据集。

<cfloop from="1" to="#arrayLen(tagArray)#" index="i">
    <cfquery name="qryGetSPFAQs#i#" datasource="#application.datasource#">
        EXEC searchFAQ '#tagArray[i]#'
    </cfquery>
</cfloop>

<cfquery name="combined" dbtype="query">
    <cfloop from="1" to="#arrayLen(tagArray)#" index="i">
        select * from qryGetSPFAQs#i#
        <cfif i lt arrayLen(tagArray)>UNION</cfif>
    </cfloop>
</cfquery>

答案 1 :(得分:1)

更直接的方式可能是这样的:

<cfset bigQ = queryNew("column")>
<cfloop from="1" to="#arrayLen(tagArray)#" index="i">
    <cfquery name="qryGetSPFAQs" datasource="#application.datasource#">
        EXEC searchFAQ '#tagArray[i]#'
    </cfquery>
    <cfset queryAddRow(bigQ)>
    <cfset querySetCell(bigQ, "column". qryGetSPFAQs)>
</cfloop>

您需要为每列提供querySetCell()分配。有关详细信息,请查看query functions in the live docs

答案 2 :(得分:0)

这是一个开箱即用的解决方案,放弃了SQL视图的StoredProc(我将解释)。

免责声明:没有看到SP源代码,我无法判断我的解决方案是否合适。我假设SP是相当基本的,我承认我通常更喜欢在视图上编译SP的执行,但SQL View的一次性执行应该优于SP x循环的次数。

首先创建一个看起来像SP中的SELECT语句的视图(减去参数化,当然 - 你将在新视图的CFQUERY中的WHERE子句中覆盖它。

其次,将循环设置为仅构建我们将用于WHERE子句的数据集。您需要使用ArrayToList和一些字符串操作来整理它,最终产品是存储在单个CF变量中的字符串,如下所示:

( 'ValueOfArrayElement1', 'ValueOfArrayElement2', 'Value_And_So_On')

使用ArrayToList的delimeter属性构建字符串非常简单,并且在循环完成后,附加左括号&amp;单引号到字符串的最左侧位置;并附加单一报价&amp;右括号到字符串中最右边的位置。

现在,编写CFQUERY语句,从视图中选择所需的列(而不是执行SP)。而不是将参数传递给SP,您将在CFQUERY中放置一个WHERE子句。

哦,顺便说一下,我说你需要一个SQL视图,但整个SELECT 可以在CFQUERY中构建。就个人而言,当我有一个多表JOIN时,我喜欢在SQL视图中定义它比CFQUERY中的JOIN更快地执行它。最终StoredProc的速度更快,但是我们的WHERE子句在编写代码和读取时比在没有循环进出SQL的情况下发送到StoredProc更友好。

如果可能的话,只有一次旅行到数据库然后返回是一个很好的目标。这就是为什么我们循环遍历数组来编写一个等于数据集中所有值的字符串。这样,我们只会执行一次查询。

SELECT Col1, Col2, Col_etc
FROM SQL_View_Name
WHERE ColumnName in #BigStringWeMadeFromArrayToList#

当渲染我们的CFQUERY时,该子句在SQL中看起来就像这样:

WHERE ColumnName in 
     ('ValueOfArrayElement1','ValueOfArrayElement2','Value_And_So_On')

所以你有它。就像我说的那样,这很好,因为它只对数据库进行一次访问,而且由于我们正在构建一个视图,性能仍然相当不错 - 比运行StoredProc 4次更好。 (没有冒犯)

我必须重复......没有看过SP代码,我不确定这是否可行。另外,放弃StoredProc用于SQL视图(RDBMS中的“较小”实体)有点奇怪,但我相信我们会获得更高的性能,我认为它也非常易读。