Настраиваемый генератор числовой последовательности для запроса

08.05.16

Разработка - Запросы

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

Пусть имеется запрос следующего вида:

ВЫБРАТЬ 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) Б

Подводя итог, можно сказать, что приведенное решение дает использованию генерируемых числовых последовательностей в запросах отсутствующую ранее гибкость. Поэтому можно надеяться, что за счет этого расширится  и область их эффективного применения.

 

Полезные ссылки:

Генерация числовой последовательности

Генерация числовой последовательности и последовательности дат при помощи языка запросов

Работаем с датами в запросе

Порождающий запрос 

Формирование списка дат в заданном диапазоне в тексте запроса

Некоторые полезные новичкам платформы 1С8.х приёмы работы с запросами - 2 часть (пример 7 Последовательность чисел, дат)

Порядковый номер в запросе (Новым простым способом)

Объектная модель запроса "Схема запроса" - теория и примеры использования

числовая последовательность числовой ряд в запросе генерация схема запроса

См. также

SALE! %

Инструментарий разработчика Роли и права Запросы СКД Программист Платформа 1С v8.3 Управляемые формы Запросы Система компоновки данных Конфигурации 1cv8 Платные (руб)

Набор инструментов программиста и специалиста 1С для всех конфигураций на управляемых формах. В состав входят инструменты: Консоль запросов, Консоль СКД, Консоль кода, Редактор объекта, Анализ прав доступа, Метаданные, Поиск ссылок, Сравнение объектов, Все функции, Подписки на события и др. Редактор запросов и кода с раскраской и контекстной подсказкой. Доработанный конструктор запросов тонкого клиента. Продукт хорошо оптимизирован и обладает самым широким функционалом среди всех инструментов, представленных на рынке.

12000 10000 руб.

02.09.2020    164801    914    402    

889

Запросы Программист Бесплатно (free)

Увидел cheatsheet по SQL и захотелось нарисовать подобное, но про запросы.

18.10.2024    10794    sergey279    18    

65

Запросы Программист Платформа 1С v8.3 Запросы Конфигурации 1cv8 Бесплатно (free)

Столкнулся с интересной ситуацией, которую хотел бы разобрать, ввиду её неочевидности. Речь пойдёт про использование функции запроса АВТОНОМЕРЗАПИСИ() и проблемы, которые могут возникнуть.

11.10.2024    5899    XilDen    36    

81

Запросы Программист Запросы Бесплатно (free)

Отлаживая взаимодействие с базой данных, мы регулярно сталкиваемся с зависающими или подозрительно долго выполняющимися обращениями, негативно влияющими на производительность. О том, как в PostgreSQL выявить подозрительные запросы, основываясь на доступной о них информации, расскажем в статье.

16.08.2024    8546    user1840182    5    

28

Математика и алгоритмы Запросы Программист Платформа 1С v8.3 Запросы Бесплатно (free)

Рассмотрим быстрый алгоритм поиска дублей с использованием hash функции по набору полей шапки и табличных частей.

08.07.2024    2596    ivanov660    9    

22

Запросы СКД Программист Стажер Система компоновки данных Россия Бесплатно (free)

Часто при разработке отчетов в СКД возникает ситуация, когда не совсем понятно, почему отчет выводит не те данные, которые нужны, либо не выводит вовсе. Возникает потребность увидеть конечный запрос, который формирует СКД. Как это сделать, рассмотрим в этой статье.

15.05.2024    9629    implecs_team    6    

48

Запросы Программист Стажер Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

Часто поступают задачи по произвольному распределению общих сумм. После распределения иногда пропадают копейки. Суть решения добавить АвтоНомерЗаписи() в ВТ распределения, и далее используя функции МАКСИМУМ или МИНИМУМ можем положить разницу копеек в первую или последнюю строку знаменателя распределения.

11.04.2024    3528    andrey_sag    10    

36
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. necropunk 9 10.05.16 12:27 Сейчас в теме
Отлично. Интересно, какие у вас на работе задачи, что требуют подобных изысканий... Как всегда прекрасный материал, спасибо.
2. ildarovich 7938 11.05.16 17:08 Сейчас в теме
Не сказал бы, что у меня на работе какие-то особенные задачи. Многие из них довольно скучные. Дело больше в желании найти красивое и эффективное решение практической задачи и полученном от этого удовольствии.

Lacoste4life; SerVer1C; Noxie41; necropunk; +4 Ответить
3. DrAku1a 1747 12.05.16 02:23 Сейчас в теме
(2) полагаю, вопрос надо задать немного по-другому: Как Вам удаётся находить такие красивые и сложные практические задачи?
К слову, Ваше имя - уже как знак качества: плюс статье так и хочется поставить ещё до начала чтения!
4. vasiliy_b 284 13.05.16 13:48 Сейчас в теме
Тоже увидел заголовок статьи и хотел уже было пройти мимо, но увидев автора, решил таки почитать, и не разочаровался. Спасибо.
5. Yashazz 4797 24.06.16 09:26 Сейчас в теме
Я чрезвычайно уважаю автора за стильность подхода к "сферическим решениям", но рад и видеть использование смешанных технологий. Я обычно практикую именно такие варианты - помесь хитрых запросов с их модификацией кодом или схемой. Похожее решение (вставку запроса как подзапроса) тоже использую, правда, иногда это становится малопрозрачным)))
6. triviumfan 97 21.11.24 15:32 Сейчас в теме
Сергей, приветствую.
Не совсем понятен практический смысл такого сложного запроса для получения последовательности, если он делается в несколько строчек:
МассивЗапросов = Новый Массив;
Для Инд = 0 По 1000 Цикл
	МассивЗапросов.Добавить("ВЫБРАТЬ " + Формат(Инд, "ЧН=0; ЧГ=0"));
КонецЦикла;
ТекстЗапроса = СтрСоединить(МассивСтрок, " ОБЪЕДИНИТЬ ВСЕ "); 
7. ildarovich 7938 21.11.24 15:55 Сейчас в теме
(6) Это не принципиальный вопрос, а просто дело вкуса. Можно написать 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1, а можно 2 * 2 * 2.
Показано, как это сделать более коротким запросом.

Вообще, мне бы хотелось, чтобы в запросе были готовые операторы для формирования искусственных таблиц и не приходилось бы лепить такие не стройные генераторы.
Оставьте свое сообщение