Новый подход к нестандартному срезу последних. Вилка Фиксина
В этой статье предлагаю пересмотреть стереотипы, касающиеся нестандартных запросов по срезам последних. Такие запросы довольно распространены, потому что возможности среза последних в 1С довольно ограничены, приходится имитировать срез последних собственным запросом. Обычно это происходит когда на каждую строку запроса нужно получить срез на свою дату, а не на общую дату отчета.
Мне нужно было по каждому товару получить последнюю и предпоследнюю цену, чтобы сравнить, было ли уменьшение цены и когда.
Тестировал в УТ 11.4.
Классический запрос, который написали бы практически все программисты 1С для решения этой задачи, использует оператор В и Максимум:
ВЫБРАТЬ ЦТекущие.Номенклатура.Ссылка КАК Ссылка, ЦТекущие.Период КАК ПериодТекущий, ЕСТЬNULL(ЦТекущие.Цена, 0) КАК ЦенаТекущая, ЦПрошлые.Период КАК ПериодПрошлый, ЕСТЬNULL(ЦПрошлые.Цена, 0) КАК ЦенаПрошлая ИЗ Справочник.Номенклатура КАК ТН ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних(, ВидЦены = &ВидЦены) КАК ЦТекущие ПО (ЦТекущие.Номенклатура = ТН.Ссылка) ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры КАК ЦПрошлые ПО (ЦПрошлые.ВидЦены = &ВидЦены) И (ЦПрошлые.Номенклатура = ТН.Ссылка) И (ЦПрошлые.Период < ЦТекущие.Период) И (ЦПрошлые.Период В (ВЫБРАТЬ МАКСИМУМ(Ц.Период) ИЗ РегистрСведений.ЦеныНоменклатуры КАК Ц ГДЕ Ц.Номенклатура = ТН.Ссылка И Ц.ВидЦены = &ВидЦены И Ц.Период < ЦТекущие.Период)) ГДЕ НЕ ЦТекущие.Цена ЕСТЬ NULL И НЕ ЦПрошлые.Цена ЕСТЬ NULL
Запрос выполняется за 0.877 секунд:
Попробуем немного более изощренный запрос:
ВЫБРАТЬ ЦТекущие.Номенклатура.Ссылка КАК Ссылка, ЦТекущие.Период КАК ПериодТекущий, ЕСТЬNULL(ЦТекущие.Цена, 0) КАК ЦенаТекущая, ЦПрошлые.Период КАК ПериодПрошлый, ЕСТЬNULL(ЦПрошлые.Цена, 0) КАК ЦенаПрошлая ИЗ Справочник.Номенклатура КАК ТН ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних(, ВидЦены = &ВидЦены) КАК ЦТекущие ПО (ЦТекущие.Номенклатура = ТН.Ссылка) ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры КАК ЦПрошлые ПО (ЦПрошлые.ВидЦены = &ВидЦены) И (ЦПрошлые.Номенклатура = ТН.Ссылка) И (ЦПрошлые.Период < ЦТекущие.Период) ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры КАК ЦВсе ПО (ЦВсе.ВидЦены = &ВидЦены) И (ЦВсе.Номенклатура = ТН.Ссылка) И (ЦВсе.Период > ЦПрошлые.Период) И (ЦВсе.Период < ЦТекущие.Период) ГДЕ ЦВсе.Цена ЕСТЬ NULL И НЕ ЦТекущие.Цена ЕСТЬ NULL И НЕ ЦПрошлые.Цена ЕСТЬ NULL
Он выполняется в два раза быстрее, за 0.246 секунд:
На мой взгляд, второй запрос пишется логичнее и понятнее. Мы смотрим, есть ли значение, которое попадает между текущей прошлой и последней ценой. Если есть, то прошлая цена не годится.
Я практически не встречал использование такой методики в запросах, поэтому назову ее скромно «вилкой Фиксина», не от названия столового прибора, а от математического метода «вилки».
Чтобы быть уверенным, что быстродействие действительно и на больших объемах товаров и цен, я протестировал запрос на файловой базе УТ 11.4 с большим количество товаров.
Вот результаты классического запроса (468 секунд):
А вот результаты вилки Фиксина (556 секунд):
Как видно, на больших объемах вилка работает несколько медленнее. Есть идеи как ускорить?
Предлагаю протестировать запросы на своей базе, особенно интересует SQL, и поделиться результатами.
Ускорение для файловой базы? Кек. Файловая база это демоверсия от 1с, неработоспособная вдобавок
Я вот думаю на файловой версии Базуху написать. А вы ее хаете.
Оригинальное решение. Спасибо, очень интересно
да, вилка оригинальное использование SQL