在循环中组合查询行

发布于 2024-09-03 08:36:32 字数 403 浏览 7 评论 0原文

我有以下 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 行的查询对象。我该如何实现这一目标?

I have the following ColdFusion 9 code:

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

The EXEC executes a stored procedure on the database server, which returns rows of data, depending on what the parameter is. What I am trying to do is combine the queries into one query object. In other words, if it loops 3 times and each loop returns 4 rows, I want a query object that has all 12 rows in one object. How do I acheive this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

深海蓝天 2024-09-10 08:36:32

您可能想要采取不同的方法(修改存储过程以接受多个参数或使用列表和 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>

You might want to take a different approach (modify your stored procedure to accept multiple arguments or use a list and fnSplit) and return the dataset all at once. However, to directly answer your question, this is how you could combine the queries as you're asking to:

You can use UNION in a Query of Queries to combine all of the datasets.

<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>
别挽留 2024-09-10 08:36:32

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

<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() 。查看实时文档中的查询函数更多信息。

A more direct way might be something like this:

<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>

You will need a querySetCell() assignment for each column. Check out the query functions in the live docs for more information.

杀お生予夺 2024-09-10 08:36:32

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

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

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

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

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

使用 ArrayToList 的 delimeter 属性构建字符串非常简单,循环完成后,将左括号和单引号附加到最左边的位置。 string; 并将单引号和右括号附加到字符串的最右侧位置。

现在,编写 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 代码的情况下,我不确定这是否可行。另外,为 SQL 视图(RDBMS 中的“较小”实体)放弃 StoredProc 有点奇怪,但我确信我们将实现更高的性能,而且我认为它也非常可读。

Here is an out of the box solution, abandoning the StoredProc for a SQL View (I'll explain).

Disclaimer: without seeing the SP source code, I can't tell if my solution fits. I'm assuming that the SP is fairly basic, and I admit I usually prefer the compiled execution of an SP over a view, but the one-time execution of a SQL View should outperform the looping of the SP x times.

First make a view that looks like the SELECT statement in the SP (minus the parameterization, of course -- you'll cover that in a WHERE clause within the CFQUERY of your new view.

Second, set up your loop to do no more than build a data set we're going to use for the WHERE clause. You'll need to use ArrayToList and a little bit of string manipulation to tidy it up, with the end product being a string stored in a single CF variable looking like this:

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

Building the string is pretty easy, using the delimeter attribute of ArrayToList, and after the loop is complete, append a Left Parenthesis & Single Quote to the Left most position of the string; and append a Single Quote & Right Parenthesis to the Right most position in the string.

Now, write the CFQUERY statement to SELECT the columns you need from your view (instead of executing your SP). And instead of passing a parameter to the SP, you're going to put a WHERE clause in the CFQUERY.

Oh, BTW, I am stating you need a SQL View, but the entire SELECT could be built in CFQUERY. Personally, when I have a multi-table JOIN, I like to define that in a SQL View where it's executed more quickly than a JOIN in CFQUERY. Ultimately a StoredProc is even faster, but our WHERE clause is much friendlier to code and read like this than it would be to send into StoredProc without looping in and out of SQL.

It's a good goal to make only one trip out to the database and back if possible. That's why we looped through the array to write a string equating to all the values in the dataset. This way, we'll only execute one query, one time.

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

when our CFQUERY is rendered, the clause will look just like this in SQL:

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

So there you have it. Like I said, this is nice because it makes only one trip to the DB, and since we are building a view, the performance will still be pretty good -- better than running a StoredProc 4+ times. (no offense)

I'll must repeat... without having seen the SP code, I'm not sure if this is do-able. Plus, it's kind of odd to abandon a StoredProc for a SQL View, a "lesser" entity in the RDBMS, but I'm sure we will achieve greater performance and I think it's pretty readable, too.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文