Пусть имеется запрос следующего вида:
ВЫБРАТЬ 2*Х + У КАК Х ИЗ (ВЫБРАТЬ 0 КАК Х) А, (ВЫБРАТЬ 0 КАК У ОБЪЕДИНИТЬ ВЫБРАТЬ 1) Б
Запрос возвращает таблицу чисел:
Х |
0 |
1 |
Ключевая особенность рассматриваемого запроса в том, что, подставив текст всего запроса вместо вложенного запроса "А", можно получить запрос
ВЫБРАТЬ 2*Х + У КАК Х ИЗ (
ВЫБРАТЬ 2*Х + У КАК Х ИЗ (ВЫБРАТЬ 0 КАК Х) А, (ВЫБРАТЬ 0 КАК У ОБЪЕДИНИТЬ ВЫБРАТЬ 1) Б
) А, (ВЫБРАТЬ 0 КАК У ОБЪЕДИНИТЬ ВЫБРАТЬ 1) Б
, возвращающий таблицу:
Х |
0 |
1 |
2 |
3 |
и так далее, получая на каждом шаге таблицу вдвое больщего размера.
В отличии от известных методов, для увеличения диапазона генерируемых чисел вдвое, здесь требуется выполнить всего одну операцию: подстановку текста всего запроса на место вложенного, что в объектной схеме запроса можно выполнить одним оператором:
ИсходныйЗапрос.Операторы[0].Источники[0].Источник.Запрос.УстановитьТекстЗапроса(
ИсходныйЗапрос.ПолучитьТекстЗапроса());
Вторым достоинством предлагаемого запроса является его самодостаточность: он не опирается ни на какие другие таблицы.
Число подстановок определяется формулой ]Ln(N) / Ln(2)[ - 1, где N- количество чисел (размер) последовательности, ][ - операция нахождения ближайшего сверху целого, а Ln(N) / Ln(2) - формула для расчета логарифм по основанию два.
В итоге текст запроса генерации последовательности можно получить с помощью такого фрагмента кода:
СхемаЗапроса = Новый СхемаЗапроса;
ИсходныйЗапрос = СхемаЗапроса.ПакетЗапросов[0];
ИсходныйЗапрос.УстановитьТекстЗапроса(
"ВЫБРАТЬ 2*Х + У Х ИЗ (ВЫБРАТЬ 0 Х) А, (ВЫБРАТЬ 0 У ОБЪЕДИНИТЬ ВЫБРАТЬ 1) Б"
);
Охват = 2;
Пока Охват < Количество Цикл
ИсходныйЗапрос.Операторы[0].Источники[0].Источник.Запрос.УстановитьТекстЗапроса(
ИсходныйЗапрос.ПолучитьТекстЗапроса());
Охват = 2 * Охват
КонецЦикла;
ИсходныйЗапрос.Операторы[0].Отбор.Добавить("2*Х + У < &Количество");
ТекстЗапроса = ИсходныйЗапрос.ПолучитьТекстЗапроса());
На практике исходный запрос можно поместить сразу на фиксированное место в модифицируемый затем пакет запросов (потребуется решить вопрос очистки и последующего восстановления реквизита "ТаблицаДляПомещения").
Гибкость предложенной структуры еще и в том, что для генерации последовательности можно применять и другие, отличные от двойки основания. Например, для основания 5 исходный запрос будет иметь вид:
ВЫБРАТЬ 5*Х + У КАК Х
ИЗ (ВЫБРАТЬ 0 Х) А,
(ВЫБРАТЬ 0 У ОБЪЕДИНИТЬ ВЫБРАТЬ 1 ОБЪЕДИНИТЬ ВЫБРАТЬ 2 ОБЪЕДИНИТЬ ВЫБРАТЬ 3 ОБЪЕДИНИТЬ ВЫБРАТЬ 4) Б
Соответствующим образом изменится и число подстановок. Оно будет определяться формулой: ]Ln(N) / Ln(5)[ - 1.
Принцип, наверное, понятен.
Обычно на практике используются основания 2, 4, 5, 6, 10. Но все же предпочтительнее использовать основание 2.
Дело в том, что в этом случае достигается максимальная экономия холостых циклов: когда полученное декартовым произведением число отсекается затем условием ГДЕ. Например, при основании 10 ряд из 101-го числа может быть сформирован из множества чисел от 0 до 999, 899 из которых будет затем отброшено. В самом худшем случае для основания 2 при неудобном количестве из 513 чисел в последовательности из произведения размером 1024 записи будут отфильтрованы всего 511 чисел, то есть почти вдвое меньше.
Кроме того, при использовании основания 2 итоговая длина текста запроса оказывается короче как в символах, так и в строках.
Стоит, однако, сказать, что наименьшими затратами в плане количества соединений и холостых циклов отличается запрос генерации последовательности, формируемый функцией ProtoText, приведенной в статье [Порождающий запрос]. Его применение сдерживает принципиальное использование неизвестного заранее количества временных таблиц, из-за чего при вставке сгенерированного запроса в схему запроса "плывут" индексы всех следующих запросов в пакете.
Есть еще один вариант исходного запроса. Изначально он несколько длиннее, но его итоговая запись короче и он требует на единицу меньше итераций цикла при подстановке, потому, что его результат сразу содержит не два, а четыре числа.
ВЫБРАТЬ 2*Х + У КАК Х
ИЗ (ВЫБРАТЬ 0 Х ОБЪЕДИНИТЬ ВЫБРАТЬ 1) А, (ВЫБРАТЬ 0 У ОБЪЕДИНИТЬ ВЫБРАТЬ 1) Б
Подводя итог, можно сказать, что приведенное решение дает использованию генерируемых числовых последовательностей в запросах отсутствующую ранее гибкость. Поэтому можно надеяться, что за счет этого расширится и область их эффективного применения.
Полезные ссылки:
Генерация числовой последовательности
Генерация числовой последовательности и последовательности дат при помощи языка запросов
Формирование списка дат в заданном диапазоне в тексте запроса
Порядковый номер в запросе (Новым простым способом)
Объектная модель запроса "Схема запроса" - теория и примеры использования