Новый подход к нестандартному срезу последних. Вилка Фиксина

В этой статье предлагаю пересмотреть стереотипы, касающиеся нестандартных запросов по срезам последних. Такие запросы довольно распространены, потому что возможности среза последних в 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, и поделиться результатами.

fixin

Программирую на 1С с 1999 года. В 1С просто Гений. В 2020 году ушел из офиса на вольные хлеба фриланса. Принимаю заказы.

Читайте также:

комментария 4

  1. Павел:

    Ускорение для файловой базы? Кек. Файловая база это демоверсия от 1с, неработоспособная вдобавок

  2. Илья:

    Оригинальное решение. Спасибо, очень интересно

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *