Заметки по SQL: Срез последних - аналог запроса

26.02.20

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

В статье описывается создание среза последних данных средствами классического языка запросов. Причем метод построения запроса был разработан еще во времена, когда автор работал с СУБД Oracle 9i и программировал на PL SQL. Основная идея заключается преобразовании запроса с подзапросом, в запрос без подзапроса (в примерах описывается преобразование до двух вложенных подзапросов). Запросы тестировались на реальных базах данных. Платформа - 1С:Предприятие 8.3 (8.3.10.2561).

1. Введение

Поскольку я занимаюсь сопровождением конфигурации - "Расчеты с населением за газ" (разработчик - ООО "АНТ-Консалт"), внедренной в 56 регионах России (цифра приблизительная), то все примеры будут основаны на данных именно этой конфигурации. Основу примеров составят запросы к регистру сведений "ПоказанияСчетчиков".

Вид запроса 1с для периодического, независимого регистра сведений с периодичностью "В пределах секунды",  который реально формируется в СУБД выглядит следующим образом:

ВЫБРАТЬ
	ВложенныйЗапрос.Оборудование КАК Оборудование,
	ВложенныйЗапрос.ПоследниеПоказанияПериод КАК ПоследниеПоказанияПериод,
	ПКУ_ПоказанияСчетчиков.Значение КАК ПоследниеПоказанияЗначение
ИЗ
	(ВЫБРАТЬ
		ПКУ_ПоказанияСчетчиков.Оборудование КАК Оборудование,
		МАКСИМУМ(ПКУ_ПоказанияСчетчиков.Период) КАК ПоследниеПоказанияПериод
	ИЗ
		РегистрСведений.ПоказанияСчетчиков КАК ПКУ_ПоказанияСчетчиков
	ГДЕ
		ПКУ_ПоказанияСчетчиков.Период <= &ДатаПоказаний
	
	СГРУППИРОВАТЬ ПО
		ПКУ_ПоказанияСчетчиков.Оборудование) КАК ВложенныйЗапрос
		ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ПоказанияСчетчиков КАК ПКУ_ПоказанияСчетчиков
		ПО ВложенныйЗапрос.Оборудование = ПКУ_ПоказанияСчетчиков.Оборудование
			И ВложенныйЗапрос.ПоследниеПоказанияПериод = ПКУ_ПоказанияСчетчиков.Период

Для простоты понимания пример приведен в синтаксисе языка запросов 1с, как реально это может выглядеть в profiler на MS SQL можно посмотреть в очень популярной статье на Инфостарте - "Регистры сведений 1С. Как это устроено.", раздел "3. Как работает СрезПоследних (СрезПервых) в запросе". 

А теперь преобразуем запрос с подзапросом в один запрос;

ВЫБРАТЬ
	ПКУ_ПоказанияСчетчиков.Значение КАК ПоследниеПоказанияЗначение,
	ПКУ_ПоказанияСчетчиков.Оборудование КАК Оборудование,
	ПКУ_ПоказанияСчетчиков.Период КАК Период
ИЗ
	РегистрСведений.ПоказанияСчетчиков КАК ПКУ_ПоказанияСчетчиков
		ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.ПоказанияСчетчиков КАК ПКУ_ПоказанияСчетчиков1
		ПО ПКУ_ПоказанияСчетчиков.Оборудование = ПКУ_ПоказанияСчетчиков1.Оборудование
ГДЕ
        ПКУ_ПоказанияСчетчиков1.Период <= &Период И
	ПКУ_ПоказанияСчетчиков.Период  <= &Период

СГРУППИРОВАТЬ ПО
	ПКУ_ПоказанияСчетчиков.Оборудование,
	ПКУ_ПоказанияСчетчиков.Значение,
	ПКУ_ПоказанияСчетчиков.Период

ИМЕЮЩИЕ
	МАКСИМУМ(ПКУ_ПоказанияСчетчиков1.Период) = ПКУ_ПоказанияСчетчиков.Период

Как видим нет ничего сверх естественного, все в рамках классического  SQL. Даже и пояснять особо ничего не нужно. Отмечу, что эта конструкция, будет являться базовой для построения запросов следующей публикации.

2. Работа с реальными данными.

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

ВЫБРАТЬ
	ПринятыеКУчетуПоказанияСрезПоследних.Период КАК Период,
	ПринятыеКУчетуПоказанияСрезПоследних.Оборудование КАК Оборудование,
	ПринятыеКУчетуПоказанияСрезПоследних.Значение КАК Значение
ИЗ
	РегистрСведений.ПринятыеКУчетуПоказания.СрезПоследних(, НЕ НеПриниматьКУчету) КАК ПринятыеКУчетуПоказанияСрезПоследних

работать будет не правильно.

Что же нам предлагают разработчики конфигурации - текст запроса:

ВЫБРАТЬ
	ПоказанияСчетчиков.Оборудование КАК Оборудование,
	ПоказанияСчетчиков.Значение КАК Значение,
	ПоказанияСчетчиков.ДатаРегистрацииИзменения КАК ДатаРегистрацииИзменения,
	ПоказанияСчетчиков.НеПриниматьКУчету КАК НеПриниматьКУчету,
	ПоказанияСчетчиков.Период КАК Период,
	ПоказанияСчетчиков.Регистратор КАК Регистратор
ПОМЕСТИТЬ втНач
ИЗ
	РегистрСведений.ПоказанияСчетчиков КАК ПоказанияСчетчиков
ГДЕ
	ПоказанияСчетчиков.Период <= &ДатаПоказаний

ИНДЕКСИРОВАТЬ ПО
	ПоказанияСчетчиков.Оборудование,
	ПоказанияСчетчиков.Период
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
	втНач.Оборудование КАК Оборудование,
	втНач.Значение КАК Значение,
	втНач.Период КАК Период
ПОМЕСТИТЬ ПКУ_ПоказанияСчетчиков
ИЗ
	втНач КАК втНач
		ВНУТРЕННЕЕ СОЕДИНЕНИЕ (ВЫБРАТЬ
			втНач.Оборудование КАК Оборудование,
			МАКСИМУМ(втНач.Регистратор) КАК Регистратор,
			втНач.Период КАК Период,
			втНач.ДатаРегистрацииИзменения КАК ДатаРегистрацииИзменения
		ИЗ
			втНач КАК втНач
				ВНУТРЕННЕЕ СОЕДИНЕНИЕ (ВЫБРАТЬ
					втНач.Оборудование КАК Оборудование,
					втНач.Период КАК Период,
					МАКСИМУМ(втНач.ДатаРегистрацииИзменения) КАК ДатаРегистрацииИзменения
				ИЗ
					втНач КАК втНач
				
				СГРУППИРОВАТЬ ПО
					втНач.Оборудование,
					втНач.Период) КАК втДни2
				ПО втНач.Период = втДни2.Период
					И втНач.ДатаРегистрацииИзменения = втДни2.ДатаРегистрацииИзменения
					И втНач.Оборудование = втДни2.Оборудование
		
		СГРУППИРОВАТЬ ПО
			втНач.Оборудование,
			втНач.Период,
			втНач.ДатаРегистрацииИзменения) КАК втДни
		ПО втНач.Период = втДни.Период
			И втНач.ДатаРегистрацииИзменения = втДни.ДатаРегистрацииИзменения
			И втНач.Регистратор = втДни.Регистратор
			И втНач.Оборудование = втДни.Оборудование
ГДЕ
	НЕ втНач.НеПриниматьКУчету

ИНДЕКСИРОВАТЬ ПО
	втНач.Оборудование,
	втНач.Период
;

////////////////////////////////////////////////////////////////////////////////
УНИЧТОЖИТЬ втНач
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
	ВложенныйЗапрос.Оборудование КАК Оборудование,
	ВложенныйЗапрос.ПоследниеПоказанияПериод КАК ПоследниеПоказанияПериод,
	ПКУ_ПоказанияСчетчиков.Значение КАК ПоследниеПоказанияЗначение
ИЗ
	(ВЫБРАТЬ
		ПКУ_ПоказанияСчетчиков.Оборудование КАК Оборудование,
		МАКСИМУМ(ПКУ_ПоказанияСчетчиков.Период) КАК ПоследниеПоказанияПериод
	ИЗ
		ПКУ_ПоказанияСчетчиков КАК ПКУ_ПоказанияСчетчиков
	
	СГРУППИРОВАТЬ ПО
		ПКУ_ПоказанияСчетчиков.Оборудование) КАК ВложенныйЗапрос
		ЛЕВОЕ СОЕДИНЕНИЕ ПКУ_ПоказанияСчетчиков КАК ПКУ_ПоказанияСчетчиков
		ПО ВложенныйЗапрос.Оборудование = ПКУ_ПоказанияСчетчиков.Оборудование
			И ВложенныйЗапрос.ПоследниеПоказанияПериод = ПКУ_ПоказанияСчетчиков.Период

Ну что ж, вполне себе работоспособный запрос . При чем вторая временная таблица "ПКУ_ПоказанияСчетчиков", очень напоминает нам аналог конструкции для регистра с периодичностью "По позиции регистратора" в СУБД, с той лишь разницей, что вместо периода используется реквизит "ДатаРегистрацииИзменения". Пример можно увидеть в уже вышеупомянутой статье - "Регистры сведений 1С. Как это устроено.", раздел "3. Как работает СрезПоследних (СрезПервых) в запросе".  Этот запрос был использован при разработке отчета в публикации "Реестр показаний по приборам учета за период с расчетом среднего потребления ресурса"

А теперь самое интересное. Преобразуем этот запрос, в запрос с одной виртуальной таблицей без подзапросов. Код запроса:

ВЫБРАТЬ
	втНач.Оборудование КАК Оборудование,
	втНач.Период КАК Период,
	втНач.Значение КАК Значение
ПОМЕСТИТЬ ПКУ_ПоказанияСчетчиков
ИЗ
	РегистрСведений.ПоказанияСчетчиков КАК втНач
		ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.ПоказанияСчетчиков КАК втНач1
		ПО втНач.Оборудование = втНач1.Оборудование
			И втНач.Период = втНач1.Период
		ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.ПоказанияСчетчиков КАК втНач2
		ПО втНач.Оборудование = втНач2.Оборудование
			И втНач.Период = втНач2.Период
ГДЕ
	НЕ втНач.НеПриниматьКУчету
	И втНач.Период <= &ДатаПоказаний

СГРУППИРОВАТЬ ПО
	втНач.Оборудование,
	втНач.Период,
	втНач.Регистратор,
	втНач.ДатаРегистрацииИзменения,
	втНач1.ДатаРегистрацииИзменения,
	втНач.Значение

ИМЕЮЩИЕ
	МАКСИМУМ(втНач2.ДатаРегистрацииИзменения) = втНач1.ДатаРегистрацииИзменения И
	МАКСИМУМ(втНач1.Регистратор) = втНач.Регистратор

ИНДЕКСИРОВАТЬ ПО
	Оборудование,
	Период
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
	ПКУ_ПоказанияСчетчиков.Оборудование КАК Оборудование,
	ПКУ_ПоказанияСчетчиков.Период КАК Период,
	ПКУ_ПоказанияСчетчиков.Значение КАК ПоследниеПоказанияЗначение
ИЗ
	ПКУ_ПоказанияСчетчиков КАК ПКУ_ПоказанияСчетчиков
		ВНУТРЕННЕЕ СОЕДИНЕНИЕ ПКУ_ПоказанияСчетчиков КАК ПКУ_ПоказанияСчетчиков1
		ПО ПКУ_ПоказанияСчетчиков.Оборудование = ПКУ_ПоказанияСчетчиков1.Оборудование

СГРУППИРОВАТЬ ПО
	ПКУ_ПоказанияСчетчиков.Оборудование,
	ПКУ_ПоказанияСчетчиков.Значение,
	ПКУ_ПоказанияСчетчиков.Период

ИМЕЮЩИЕ
	МАКСИМУМ(ПКУ_ПоказанияСчетчиков1.Период) = ПКУ_ПоказанияСчетчиков.Период

     Немного анализа с аналогиями. Как видим первое соединение с втНач1, есть аналог первого подзапроса разработчиков конфигурации, второй виртуальной таблицы "ПКУ_ПоказанияСчетчиков" с условием  втНач.ДатаРегистрацииИзменения = втДни2.ДатаРегистрацииИзменения, только у нас условие  МАКСИМУМ(втНач1.ДатаРегистрацииИзменения) = втНач.ДатаРегистрацииИзменения. Естественно это соединение выполняется первым. И соответственно второй подзапрос имеющий свой подзапрос соединяющийся условием втНач.Регистратор = втДни.Регистратор, соответствует условию нашего запроса МАКСИМУМ(втНач2.Регистратор) = втНач.Регистратор второго соединения с регистром сведений ПоказанияСчетчиков втНач2. Ну, а с выходным запросом мы уже познакомились во введении к данной статье.

     Поскольку здесь сравниваются два запроса по реальным данным, уместно будет привести данные по их быстродействию. Так вот, первый запрос работает медленнее чем предложенный вариант приблизительно на 25% (обрабатывается 105 566 записей), при первом запуске в консоли запросов (не кешируемые запросы). Причем при повторном запуске (кешируемые запросы),  разность в скорости выполнения достигает порядка 50%, то есть предложенный вариант лучше кешируется, за счет отсутствия вложенных запросов. База данных расположена на MS SQL сервере.

    Таким образом получено реальное улучшение быстродействия запроса, в случае когда стандартными средствами 1с (виртуальными таблицами, срез последних) корректно решить задачу не не удалось.

3. Формализация результата

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

 
 
ВЫБРАТЬ
	втНач.ПолеОдин КАК ПолеОдин,
	втНач.ПолеДва КАК ПолеДва,
	втНач.Период КАК Период
ПОМЕСТИТЬ ВремТабл
ИЗ
	РегистрСведений.ДанныеРегистра КАК втНач
		ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.ДанныеРегистра КАК втНач(1)
		ПО втНач.ПолеОдин = втНач(1).ПолеОдин
		 И втНач.ПолеДва = втНач(1).ПолеДва
		ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.ДанныеРегистра КАК втНач(2)
		ПО  втНач(1).ПолеОдин = втНач(2).ПолеОдин
		  И втНач(1).ПолеДва = втНач(2).ПолеДва
		...............................................................
		ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.ДанныеРегистра КАК втНач(N)
		ПО втНач(N-1).ПолеОдин = втНач(N).ПолеОдин
		 И втНач(N-1).ПолеДва = втНач(N).ПолеДва
			
ГДЕ
	втНач.Период <= &ДатаПолучения И
    втНач(1).Период <= &ДатаПолучения И
    ...
    втНач(N).Период <= &ДатаПолучения 

СГРУППИРОВАТЬ ПО
	втНач.ПолеОдин,
	втНач.ПолеДва,
	втНач.Период,
	втНач.ПериродическийРеквизит,
	втНач(1).ПериродическийРеквизит(1),
	...................................
	втНач(N-1).ПериродическийРеквизит(N)
	
ИМЕЮЩИЕ
	МАКСИМУМ(втНач(1).ПериродическийРеквизит(1)) = втНач.ПериродическийРеквизит
	МАКСИМУМ(втНач(2).ПериродическийРеквизит(2)) = втНач(1).ПериродическийРеквизит(1) И
	................................................................................
	МАКСИМУМ(втНач(N).ПериродическийРеквизит(N)) = втНач(N-1).ПериродическийРеквизит(N-1) 

 

 

 

См. также

Infostart Toolkit: Инструменты разработчика 1С 8.3 на управляемых формах

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

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

13000 руб.

02.09.2020    119908    656    389    

701

Для чего используют конструкцию запроса "ГДЕ ЛОЖЬ" в СКД на примере конфигурации 1С:ERP

Запросы СКД Платформа 1С v8.3 Запросы Система компоновки данных 1С:ERP Управление предприятием 2 Бесплатно (free)

В типовых конфигурациях разработчики компании 1С иногда используют в отчетах, построенных на СКД, такую конструкцию, как "ГДЕ ЛОЖЬ". Такая конструкция говорит о том, что данные в запросе не будут получены совсем. Для чего же нужен тогда запрос?

13.02.2024    5618    KawaNoNeko    23    

23

Набор-объект для СКД по тексту или запросу

Запросы СКД Платформа 1С v8.3 Управляемые формы Конфигурации 1cv8 Абонемент ($m)

Есть список полей в виде текста, или запрос - закидываем в набор СКД.

1 стартмани

31.01.2024    1964    2    Yashazz    0    

29

Запрос 1С copilot

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

Пишем на человеческом языке, что нам надо, и получаем текст запроса на языке 1С. Используются большие языковые модели (LLM GPT) от OpenAI или Яндекс на выбор.

5 стартмани

15.01.2024    6089    29    mkalimulin    23    

48

PrintWizard: поддержка представлений ЗУП в конструкторе

Инструментарий разработчика Запросы Платформа 1С v8.3 Бесплатно (free)

Одной из интересных задач, стоящих в процессе разработки, была поддержка механизма представлений в ЗУП. Но не просто возможность исполнения запросов с ними. Основная проблема была в том, чтобы с ними было удобно работать, а именно: создавать, модифицировать и отлаживать. Кратко о том, что в итоге получилось...

14.12.2023    1714    vandalsvq    7    

28

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

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

Далеко уже не новый тип данных "Схема запроса". Статья о том, как использовать его "попроще". Примеры создания текста запроса с нуля и изменение имеющегося запроса.

06.12.2023    5282    user1923546    26    

43

Начните уже использовать хранилище запросов

HighLoad оптимизация Запросы

Очень немногие из тех, кто занимается поддержкой MS SQL, работают с хранилищем запросов. А ведь хранилище запросов – это очень удобный, мощный и, главное, бесплатный инструмент, позволяющий быстро найти и локализовать проблему производительности и потребления ресурсов запросами. В статье расскажем о том, как использовать хранилище запросов в MS SQL и какие плюсы и минусы у него есть.

11.10.2023    15954    skovpin_sa    14    

97
Комментарии
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
1. Batman 165 16.01.19 12:25 Сейчас в теме
"...автор работал с СУБД Orakle 9i" - опечатка?
2. Fox-trot 156 16.01.19 12:40 Сейчас в теме
видимо настолько это давно было, что забыл как пишется
3. IVC_goal 208 16.01.19 13:33 Сейчас в теме
Виноват исправлю. А было это 9 лет назад
4. laby 23.01.19 10:35 Сейчас в теме
ничего не понятно, зачем куча вложенных запросов. В первом пункте ещё как-то понятно, а пункт два - это что-то с чем-то ...
conductor; +1 Ответить
5. IVC_goal 208 23.01.19 11:04 Сейчас в теме
(4) Первый вложенный запрос отбирает последние введенные показания по ДатаРегистрацииИзменения. Второй вложенный запрос отбирает последний документ регистрации для введенных показаний на ДатаРегистрацииИзменения. И последний запрос отбирает последний период, когда были введены показания.
6. ElKrab 26.02.20 10:16 Сейчас в теме
по п.1 и далее пришёл к выводу, что в блок ГДЕ необходимо добавить аналогичное условие для присоединяемой таблицы. Иначе не получить значения для предыдущего периода.

исходная таблица содержит 2 строки:

показатель: шаблон: начало действия:
c3c106df-8028-c5c5-1757-f46ac246dcf0 ОРВИ 2018-01-01
c3c106df-8028-c5c5-1757-f46ac246dcf0 ОРВИ04 2018-04-01

запрос:
sel ect
	т0.показатель_отчёта,
	т0.шаблон_поиска,
	т0.начало_действия
fr om
	public.map_шаблоны_показателей_отчётов т0
join public.map_шаблоны_показателей_отчётов т1 on
	т0.показатель_отчёта = т1.показатель_отчёта
where
	--т1.начало_действия <=  $период and 
	т0.начало_действия <= $период
group by
	т0.показатель_отчёта,
	т0.шаблон_поиска,
	т0.начало_действия
having
	max(т1.начало_действия) = т0.начало_действия
Показать


если $период = '2018-03-01', то результат запроса пустой,
если раскомментить второе условие, то результат даст ожидаемую строку
c3c106df-8028-c5c5-1757-f46ac246dcf0 ОРВИ 2018-01-01
7. IVC_goal 208 26.02.20 14:20 Сейчас в теме
(6) Вы правы это условие необходимо добавить,если вводится ограничение по дате
8. victor_k 95 28.12.20 02:14 Сейчас в теме
А так что не пойдет?
|//ВЫБРАТЬ
	|//	КадровыеПерем.Должность,
	|//	КадровыеПерем.Категория
	|//ИЗ
	|//	РегистрСведений.КадровыеПеремещения.СрезПоследних(&НаДату, 
	|//		Сотрудник = &Сотрудник 
	|//		И Магазин = &Магазин
	|//	) КАК КадровыеПерем
	|
	|ВЫБРАТЬ ПЕРВЫЕ 1
	|	КадровыеПерем.Должность,
	|	КадровыеПерем.Категория
	|ИЗ
	|	РегистрСведений.КадровыеПеремещения КАК КадровыеПерем
	|ГДЕ	
	|	КадровыеПерем.Период <= &НаДату
	|	И КадровыеПерем.Сотрудник = &Сотрудник 
	|	И КадровыеПерем.Магазин = &Магазин
	|УПОРЯДОЧИТЬ ПО
	|	КадровыеПерем.Период УБЫВ
Показать
9. IVC_goal 208 28.12.20 09:36 Сейчас в теме
(8)Конечно пойдет. Только надо сравнить, что пойдет быстрее
11. AlexO 135 01.07.21 23:21 Сейчас в теме
(9) так это понятно, что по дате нужно ограничить обе таблицы, раз уж их соединяем внутренним join.
А без этого неудивительно, что дает пустую таблицу.
12. AlexO 135 01.07.21 23:26 Сейчас в теме
(8) не пойдет. Вы получаете первую попавшуюся под руку запись, а не последнюю по дате.
Не говоря уже о том, что подобным запросом данные по всем сотрудникам вы получите разве что в цикле.
16. victor_k 95 04.07.21 16:48 Сейчас в теме
(12) не первую, а последнею по условию, прежде чем утверждать, тестировать надо... со вторым утверждение согласен...
10. AlexO 135 01.07.21 23:19 Сейчас в теме
(0)
ИМЕЮЩИЕ
	МАКСИМУМ(ПКУ_ПоказанияСчетчиков1.Период) = ПКУ_ПоказанияСчетчиков.Период

При прочих равных - такой код отберет только максимальные даты, например, внутри договора или адреса, напрочь игнорируя различие по оборудованию.
Т.е. имея по договору три различных оборудования с датами 01.10.2021, 01.10.2021 и 01.01.2020 - получим только два с максимальными датами 01.10.2021.

Таким образом получено реальное улучшение быстродействия запроса, в случае когда стандартными средствами 1с (виртуальными таблицами, срез последних) корректно решить задачу не не удалось.

СрезПоследних не отработает в двух случаях: когда нужен отбор по реквизитам регистра (СрезПоследних не поможет вообще никак), и если строки в регистре физически оказались перепутаны, и на оси времени строка со "старыми" данными оказалась ниже (позже) строки с последними данными.
Во всех остальных случаях о некорректности работы СрезПоследних речи не идет в принципе.
14. AlexO 135 01.07.21 23:52 Сейчас в теме
(10) дополнение:
и если строки в регистре физически оказались перепутаны, и на оси времени строка со "старыми" данными оказалась ниже (позже) строки с последними данными.
в этом случае СрезПоследних возвратит неправильные данные согласно и строго в рамках некорректного ввода.
13. AlexO 135 01.07.21 23:41 Сейчас в теме
(0)
Исходя из выше изложенного материала, можно предложить формализованную методику построения запроса получения среза последних данных

Нельзя.
Для СрезПоследних специально организуется соединение таблицы самой с собой, чтобы выбрать максимальный период - а не просто некие таблицы последовательно соединяются между собой.
Или у вас одна таблица - N-раз подряд соединяется сама с собой? Для чего вообще?
Да и очень сомнительно быстродействие такого бутерброда соединений более трех-четырех, у вас обрабатываемые данные растут в таком случае по геометрической прогрессии, какое уж тут "50% выигрыша скорости".
На данный момент самые быстрые запросы в 1С - это пакетные и временные таблицы. А ваш бутерброд уже после 8-9-го соединения встанет колом.
15. IVC_goal 208 02.07.21 05:15 Сейчас в теме
(13)
Да и очень сомнительно быстродействие такого бутерброда соединений более трех-четырех, у вас обрабатываемые данные растут в таком случае по геометрической прогрессии, какое уж тут "50% выигрыша скорости".
Великолепное, умозрительное предположение, которое можно рассматривать как гипотезу. Приведу такие жэ умозаключения, которые ни к чему не обязывают.
1. Скорость тестировалась не клиент серверной базе (MS SQL). Надеюсь вам известно, что там запросы переводятся в классический SQL код и СБД, оптимизирует запрос по своим алгоритмам.
Утверждение-
(13)
На данный момент самые быстрые запросы в 1С - это пакетные и временные таблицы.

может не работать
2. Приведенное сравнения быстродействия, основаны на работе с реальными базами, а не умозрительно-предположительно.
17. Said-We 19.04.23 17:54 Сейчас в теме
(1) А такой схематический запрос будет аналогом среза последних или нет? :-)
sel ect
    *
fr om
    (select
           row_number() over(partition by t.izmer1, t.izmer2...t.izmerN ORDER BY t.period DESC) as npp
          ,t.period

          ,t.izmer1
          ,t.izmer2
           ...
          ,t.izmerN

          ,t.resurs_rekvizit1
          ,t.resurs_rekvizit2
           ...
          ,t.resurs_rekvizitN
     fr om
           PC_name as t
     where
           t.period <= &ДатаХ AND
           условия внутри скобок среза на поля <t.izmer1, t.izmer2...t.izmerN> и на поля <t.resurs_rekvizit1, t.resurs_rekvizit2,...t.resurs_rekvizitN>
     ) as t
wh ere
     t.npp = 1
Показать
18. IVC_goal 208 20.04.23 14:59 Сейчас в теме
(17) Судя по тексту запроса вы используете аналитическую функцию нумерации строк по измерениям с убыванием по периоду. На выходе берется запись с номером 1, то есть последнее значение. Предварительный анализ показывает, что запрос работоспособный, но это утверждение нуждается в проверке. Запрос использует подзапрос, что делает невозможным построение индекса, это увеличивает время выполнения. Возможно лучше разбить запрос на два запроса.
Подобную нумерацию можно получить и не используя аналитическую функцию. Например как это сделано в статье Запрос, получающий изменения ресурса в регистрах сведений по датам изменения за период
19. Said-We 20.04.23 15:41 Сейчас в теме
(18)
Подобную нумерацию можно получить и не используя аналитическую функцию.

Можно, но это тормозные JOIN-ы. А если row_number() существует, то почему её не использовать? Тем более, если мы говорим не про 1С запросы, а про запросы, которые строит 1С к СУБД.
row_number() - достаточно шустрая функция даже с группировками (partition by).
Всего-то надо, либо допилить файловую 1С в части оконных функций, либо (и лучше ИМХО) отказаться от файловой в пользу бесплатного SQL сервера, например PsgSQL, так как его поддержка уже есть. Были же в 1С 77 версии на пять пользователей и т.д. Т.е. вопрос только в проверке лицензии и маркетинге.
С 2018 года даже SQLite умеет оконные функции, а этот сервер разрабатывает и поддерживает пол человека.

По поводу подзапросов.
Когда 1С переводит на язык запросов SQL к СУБД, то там есть позапросы? Джоины и группировки при расчете максимума есть?
20. IVC_goal 208 20.04.23 16:16 Сейчас в теме
(19) В статье Регистры сведений 1С. Как это устроено рассмотрены запросы формирующиеся 1С на стороне SQL Сервера
21. Said-We 20.04.23 16:20 Сейчас в теме
(20) Я это читал и не только это. Поэтому такой вопрос и задал. Это риторический вопрос.
Оставьте свое сообщение