Как я могу использовать UNION типа «запрос-запрос» для n-наборов записей, когда требуется определение области видимости? - PullRequest
5 голосов
/ 27 января 2009

Я бы хотел иметь возможность сделать запрос к UNION с неизвестным количеством записей. Однако при выполнении запроса по запросу точки или скобки не допускаются в именах наборов записей.

Например, это не получается:

<cfquery name="allRecs" dbtype="query">
    SELECT * FROM recordset[1]
    UNION
    SELECT * FROM recordset[2]
</cfquery>

Использование динамических имен переменных, таких как "набор записей1", работает, но это функция и должна быть в области видимости, поэтому я не могу динамически создавать имена переменных без утечек памяти в постоянном объекте.

Есть еще идеи?

Ответы [ 4 ]

2 голосов
/ 28 января 2009

После публикации вопроса я придумал пару решений, но там может быть и лучшее.

  • Я мог бы написать динамически именованные переменные в область аргументов и затем ссылаться на них без их области в запросе

  • Создайте функцию, которая принимает 2 набора записей в качестве аргументов и возвращает один объединенный набор записей. Это может быть зациклено, чтобы постепенно добавлять набор записей за раз. Я уверен, что это очень неэффективно по сравнению со всеми UNION-ами в одном запросе.

1 голос
/ 03 февраля 2009

все решения, добавленные здесь, должны работать для вас, но я также хотел бы отметить, что в зависимости от объема данных, с которыми вы работаете, и базы данных, которую вы используете, вам, возможно, лучше попытаться найти способ сделать это на сторона базы данных. С очень большими наборами записей может быть полезно записать записи во временную таблицу и выбрать их снова, но в любом случае, если вы можете каким-либо образом переписать запросы, чтобы позволить базе данных обрабатывать это в первую очередь, вы будете лучше.

1 голос
/ 28 января 2009

После небольшого осмотра я нашел это: queryConcat на CFLib.org. Он использует queryaddrow / querysetcell для объединения двух запросов.

Я добавил быструю функцию (без проверки ошибок или проверки данных, поэтому я бы не использовал ее как есть):

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

В качестве теста я скинул это вместе:

Что, на самом деле, дает вам Фреда / Сэмми / Фреда.

Возможно, это не самая эффективная реализация, но вы всегда можете изменить код вставки / объединения, чтобы сделать его быстрее, если хотите. Главным образом я стремился написать как можно меньше кода самостоятельно. : -)

1 голос
/ 28 января 2009

Сложное задание. Я мог бы представить решение с вложенным циклом на основе GetColumnNames(), используя QueryAddRow() и QuerySetCell(). Это не будет самым эффективным, но это не очень медленно. Конечно, зависит от размера задания.

Ваше «создание функции, объединяющей два набора записей», может быть значительно более эффективным, если вы создадите ее, например, для принятия десяти аргументов. Изменить 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>
...