Представим, что наши сотрудники работают не на малую полуподвальную организацию, а на крупное оптово-розничное предприятие. Имея в месяц по 10000 отгрузок оптовым и розничным покупателям в месяц, наша компания данным запросом заставит сервер сильно задуматься.
Необходимо оптимизировать запрос и я покажу, как я это сделал. Кто-то скажет, что то, что я здесь опишу - это само собой разумеющееся, но иногда те решения, которые лежат на поверхности, не всегда видны. Я не изобрел велосипед, а просто стараюсь помочь тем, кто не смог или не успел дойти до этого самостоятельно.
За основу я возьму запрос с временными таблицами, так как по моему мнению, так будет более понятно.
ВЫБРАТЬ
Договор.Сумма КАК Сумма,
Договор.Ссылка КАК Ссылка,
МАКСИМУМ(Руководители.Период) КАК Период,
Договор.Сотрудник КАК Сотрудник
ПОМЕСТИТЬ РуководителиДоговоров
ИЗ
Документ.Договор КАК Договор
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.Руководители КАК Руководители
ПО Договор.Сотрудник = Руководители.Сотрудник
И Договор.Дата >= Руководители.Период
ГДЕ
Договор.Дата МЕЖДУ &Дата1 И &Дата2
СГРУППИРОВАТЬ ПО
Договор.Сумма,
Договор.Ссылка,
Договор.Сотрудник
;
ВЫБРАТЬ
РуководителиДоговоров.Ссылка КАК Договор,
РуководителиДоговоров.Сумма,
Руководители.Руководитель
ИЗ
РуководителиДоговоров КАК РуководителиДоговоров
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.Руководители КАК Руководители
ПО РуководителиДоговоров.Период = Руководители.Период
И РуководителиДоговоров.Сотрудник = Руководители.Сотрудник
Если мы посмотри на сам запрос, то становится понятно, что большие порции информации будут обрабатываться в соединениях. Уменьшив количество данных в соединениях мы существенно ускорим выполнение запроса.
Для этого в контексте нашего запроса необходимо получить на каждую дату и каждого сотрудника его руководителя. С большое вероятностью можно сказать, что в один день сотрудник сделает более 1 продажи, а руководитель назначается не ежесекундно, а как минимум не чаще, чем раз в день.
Выбираем из таблицы договоров только конец дня даты договора и сотрудника с инструкцией РАЗЛИЧНЫЕ, чтобы избежать дублирование строк. Таким образом получим таблицу, которая будет содержать данные, когда и у какого сотрудника были продажи. По этой таблице получаем для каждой строки руководителя для сотрудника на указанную дату. В результате получаем таблицу: дата продажи, сотрудник, руководитель. В итоге связываем таблицу договоров с полученной таблицей.
Вот итоговый запрос:
ВЫБРАТЬ РАЗЛИЧНЫЕ
КОНЕЦПЕРИОДА(Договор.Дата, ДЕНЬ) КАК Дата,
Договор.Сотрудник
ПОМЕСТИТЬ ДатыДоговоров
ИЗ
Документ.Договор КАК Договор
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
ДатыДоговоров.Дата,
ДатыДоговоров.Сотрудник,
МАКСИМУМ(Руководители.Период) КАК Период
ПОМЕСТИТЬ ПериодРуководителя
ИЗ
ДатыДоговоров КАК ДатыДоговоров
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.Руководители КАК Руководители
ПО ДатыДоговоров.Дата >= Руководители.Период
И ДатыДоговоров.Сотрудник = Руководители.Сотрудник
СГРУППИРОВАТЬ ПО
ДатыДоговоров.Дата,
ДатыДоговоров.Сотрудник
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
ПериодРуководителя.Дата,
ПериодРуководителя.Сотрудник,
Руководители.Руководитель
ПОМЕСТИТЬ РуководителиПоДатам
ИЗ
ПериодРуководителя КАК ПериодРуководителя
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.Руководители КАК Руководители
ПО ПериодРуководителя.Период = Руководители.Период
И ПериодРуководителя.Сотрудник = Руководители.Сотрудник
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
Договор.Ссылка КАК Договор,
Договор.Сумма,
РуководителиПоДатам.Руководитель
ИЗ
Документ.Договор КАК Договор
ЛЕВОЕ СОЕДИНЕНИЕ РуководителиПоДатам КАК РуководителиПоДатам
ПО КОНЕЦПЕРИОДА(Договор.Дата, ДЕНЬ) = РуководителиПоДатам.Дата
И Договор.Сотрудник = РуководителиПоДатам.Сотрудник
В дополнение ко всему хочу отметить, что по моим наблюдениям запросы с временными таблицами выполняются медленнее, чем конструкции с вложенными запросами, но вложенные запросы гораздо сложнее в понимании. Данный запрос несложно переделать в конструкцию с вложенными таблицами, поэтому я не буду приводить здесь пример такой конструкции.
Если кому-то сложно понять конечный запрос - прочитайте данную статью, чтобы знать, с чего все началось.
Спасибо за внимание.