var スコープが必要な場合、n レコードセットでクエリオブクエリ UNION を使用するにはどうすればよいですか?
-
20-08-2019 - |
質問
不明な数のレコードセットを UNION するクエリのクエリを実行できるようにしたいと考えています。ただし、クエリ対クエリを実行する場合は、レコード セット名にドットや括弧を使用することはできません。
たとえば、これは失敗します。
<cfquery name="allRecs" dbtype="query">
SELECT * FROM recordset[1]
UNION
SELECT * FROM recordset[2]
</cfquery>
「recordset1」などの動的変数名を使用することは機能しますが、これは関数内であり、var スコープにする必要があるため、永続化されたオブジェクトでメモリ リークを発生させずに変数名を動的に構築することはできません。
他に何かアイデアはありますか?
解決
困難な作業。私が使用してGetColumnNames()
とQueryAddRow()
、QuerySetCell()
に基づいて、ネストされたループを備えたソリューションを想像できます。これは、最も効率的な1ではありませんが、それは本当に遅いではありません。もちろん、タスクのサイズによって異なります。
あなたの「2つのレコードセットを組み合わせた機能を作成するには、」はるかに効率的にすることができました。その場でSQLを変更します:
<cfset var local = StructNew()>
<cfquery name="local.union" dbtype="query">
SELECT * FROM argument1
<cfloop from="2" to="#ArrayLen(arguments)#" index="local.i">
<cfif IsQuery(arguments[local.i])>
UNION
SELECT * FROM argument#local.i#
</cfif>
</cfloop>
</cfquery>
<cfreturn local.union>
他のヒント
質問を投稿した後、いくつかの解決策を思いつきましたが、もっと良い解決策があるかもしれません
動的に名前が付けられた変数を引数スコープに書き込み、クエリでスコープなしで変数を参照できます。
2 つのレコードセットを引数として受け取り、結合された 1 つのレコードセットを返す関数を作成します。これをループして、一度にレコードセットを徐々に追加できます。ただし、これは 1 つのクエリですべての UNION を実行することに比べて、非常に非効率であることは確かです。
チャンスをうかがっの迅速なビットの後、私はこれを見つけました: queryConcat のCFLib.orgで。これは、2つのクエリを連結するqueryaddrow / querysetcellを使用します。
私は(エラーチェック、またはデータ検証で、SO-であるように私はそれを使用することはありません)迅速な機能を追加します:
<cffunction name="concatenate">
<cfset var result = arguments[1]>
<cfloop from="2" to="#arraylen(arguments)#" index="i">
<cfset result=queryconcat(result, arguments[i])>
</cfloop>
<cfreturn result>
</cffunction>
テストとして、私はこれを一緒に投げます:
どのません、実際には、あなたのフレッド/サミー/フレッドを与えます。
これはおそらく最も効率的な実装ではありませんが、あなたが望むならば、あなたは常にそれを高速化するために、インサート/労働組合のコードを変更することができます。ほとんどの場合、私は自分で可能な限り小さなコードを書くために目指していました。 : - )
ここで追加の解決策のすべてはあなたのために動作するはずですが、私はまた、あなたが作業しているどのくらいのデータに依存し、使用しているデータベース、あなたがこれを行う方法を見つけようとしたほうが良いかもしれないことは言うだろうデータベース側。あなたはどのような方法でデータベースは、あなたがなります最初の場所でこれを処理できるようにクエリを書き直すことができれば、非常に大きなレコードセットで、一時テーブルにレコードを書き込み、再びそれらを選択することは有益ではなく、いずれかの方法かもしれませんほうます。