Имя: Пароль:
1C
 
Подход к написанию сложных запросов
0 Гений 1С
 
гуру
04.08.06
10:02
Сегодня мне в башку пришла идея по поводу написания сложных запросов. Попробую изложить ее на пальцах, то бишь на примерах.
1. Допустим у нас должна быть виртуальная таблица Прибыль, рассчитываемая сложными запросами, из которой мы хотим извлекать данные. По идее хотелось бы, чтобы эта таблица была описана только в одном месте кода, чтобы при изменении алгоритма расчета прибыли не пришлось менять тексты всех запросов.

2. Другой пример. Есть результат запроса, в котором есть колонка товар. Нужно добавить в эту таблицу колонку остаток, которая показывает остаток товара.
Аналогичный пример – есть таблица, где есть колонка «сотрудник», нужно добавить из регистра сведений статус сотрудника.

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

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

Это еще один из способов борьбы со сложностью запросов.
1 ТелепатБот
 
гуру
04.08.06
10:02
2 Херрес
 
04.08.06
10:06
Свой построитель запроса, что ли ? :)
3 mikecool
 
04.08.06
10:08
(0) что есть сложный запрос? построитель дает офигенную возможность для разработки запроса любого уровня сложности - имхо, как человека писавшего запросы без всяких построителей...
4 mikecool
 
04.08.06
10:10
(+3) если данные есть в базе - их можно извлечь одним запросом... без всяких ТЗ и проч.
5 Гений 1С
 
гуру
04.08.06
10:19
(3) вот в том и соль, чтобы не юзать построитель, а программно указывать что надо, смотри внимательно примеры
6 Гений 1С
 
гуру
04.08.06
10:19
счас сижу, пытаюсь такую шнягу написать для простых примеров
7 mikecool
 
04.08.06
10:24
(5) пример 1 - представление
все остальное: пять переменных - БлокSELECT, БлокFROM, БлокWHERE, БлокGROUP, Блок ORDER(можно и другие) и процедурку , которая соберет запрос...
8 Гений 1С
 
гуру
04.08.06
10:25
(7) ну пока идея только созрела, нужно обкатать на примерах, а то я уже забодался во всех запросах писать, что мне нужны только открытые договоры и т.п.
Сделал бы себе виртуальную таблицу ОткрытыеДоговоры - и в путь.
9 Гений 1С
 
гуру
04.08.06
10:31
По идее можно рассматривать множество плоских таблиц, которые строятся по тем или иным алгоритмам и которые можно:
1. соединять по некоторым связям JOIN.
2. объединять.
10 acsent
 
04.08.06
10:32
Читабельность запроса пропадет
11 Гений 1С
 
гуру
04.08.06
10:32
(10) я бы предпочел отсутствие читабельности в пользу гибкости.
12 mikecool
 
04.08.06
10:33
(10) пофигу читабельность - лишь бы правильно и быстро работало :-)
13 mikecool
 
04.08.06
10:33
(+12) в отладчике можно почитать ...
14 AntonioS
 
04.08.06
10:37
можно следующим образом:
1. пишешь запрос
ВЫБРАТь
ИЗ #Прибыль()# КАК Прибыль

2. Пишешь функцию парсера, которой передаешь текст запроса, а она подставляет вместо таблицы подзапрос

3. В итоге получится текст:
ВЫБРАТь
ИЗ
-- текст подставленный парсером
(выбрать из РегистрНакопления.ПартииТоваров.Остатки()
и т.д
)
--
КАК Прибыль
15 колодина
 
04.08.06
10:38
напомнило мне - был у нас мужик, увлеченный идей "красивого программирования", написал программу, которая выдавала "красивый" программный код... не прижилось как-то...
16 Гений 1С
 
гуру
04.08.06
10:39
(14) думаю лучше описывать запрос в виде структуры - более гибко.
(15) извини колодина, запарился писать одно и то же по 100 раз... хочется универсальности. Сегодня их одни данные по прибыли интересуют, завтра другие. Копипастить противно
17 acsent
 
04.08.06
10:41
(16) Жди 8.1 - там будут временные таблицы
18 колодина
 
04.08.06
10:41
(16) надо тогда отчет написать по прибыли, в который пользхователь мог бы сам вносить изменения.... а идея твоя по-моему не взлетит... может ошибаюсь коненчо
19 AntonioS
 
04.08.06
11:01
(16) в виде структуры это как?
20 PVasili
 
04.08.06
11:14
(8)В SQL это называется view, в 8 они используются, imho, только в срез первых/последних
21 rsv
 
04.08.06
11:22
(0) :) И в  7ке под SQL  успешно юзаю # и ##  таблички. Причем при left join    с табличкой полученной из запроса или вьюхи может вылится в дикие тормоза. А соединения  c # на порядки быстрее.
22 Гений 1С
 
гуру
04.08.06
11:23
(19) Структура, в которой иерархически представлен текст запроса - т.е. какие колонки получаются, какие условия используются и т.п.
(17) Это должно быть пошустрее временных таблиц. И работать может уже сейчас.
(20) да, что-то вроде вью.
(21) что такое # и ## таблички???
23 PVasili
 
04.08.06
11:30
(21)"SQL" и "SQL в 7" 2 огромных разницы...

(22)Временные таблицы где будут создаваться? Если на клиенте - это тормоза...

Если еще для создания вью использовать sp на сервере - вопрос о производительности отпал бы совсем. А как быть при изменении таблиц?
Но судя по всему этому не бывать, и нужно корячиться через прокладку сервера 1С :(.
24 Гений 1С
 
гуру
04.08.06
11:39
Например, соединение двух таблиц.
Нужно знать имя каждой таблицы ИмяТаблицы и колонки, которые участвуют в соединении, также условие соединения.
SELECT Т1.К1, Т1.К2, … Т1.КN, Т2.К1, Т2.К2, … Т1.КМ
FROM Т1 LEFT JOIN Т2 ON Т1.К1=Т2.К2
Допустим у нас есть запрос, который выдает некий список товаров Товары и запрос, который выдает остатки по товарам Остатки.
Тогда, чтобы получить запрос, который будет выдавать список товаров с остатками, нам нужно выполнить соединение типа:
SELECT Товары.Товар, Товары.Артикул, Остатки.Остаток, Остатки.Склад
FROM (Запрос 1) КАК Товары LEFT JOIN (Запрос 2) Как Остатки ON Товары.Товар=Остатки.Товар

Но есть вопрос по производительности – таблица остатков формируется по всем товарам или нет?
25 Гений 1С
 
гуру
04.08.06
11:41
Т.е на языке 1с я пишу запрос1 для получения списка товаров. У меня есть также запрос 2 для получения остатков.
Я говорю - мне нужно для таблицы запроса 1 получить колонку остаток из таблицы 2.
Программа должна сообразить, как ей оптимально соединить эти две таблицы.
26 SnarkHunter
 
04.08.06
11:43
Я в шоке...
27 Гений 1С
 
гуру
04.08.06
11:45
(26) откеда такие эмоции?
28 rsv
 
04.08.06
11:47
Есть понятие оптимизатор запросов и план выполнения запроса. Это удел сервака СУБД.
29 rsv
 
04.08.06
11:51
Как вызывается этот запрос. С генерацией нового плана запроса или с использованием имеющегося (экономия времени)- эти ты управлять не могешь. Так как прослойка 1С. Ты можешь инрраться с хинтами на join и прочее. Но это все мимо . Join в твоем варианте с запрос2  может тормозить. В варианте с временной таблицей проще , но такого понятия в 1С нет.
30 PVasili
 
04.08.06
11:53
(25)В случае с view будет примерно как FROM view_Запрос КАК Товары LEFT JOIN ...
(28)А ты уверен, что сервер 1С его строит наиболее оптимально в каждом случае? Почему не допустить к этому пользователя желающих соптимизировать запросы?
(29)А где будут данные из временных таблиц (8.1) на сервере или клиенте?
31 Херрес
 
04.08.06
11:59
(30) временные таблицы в 8.1 будут на сервере
32 Гений 1С
 
гуру
04.08.06
12:01
Продолжая теоретические изыскания по JOIN.
Те же 2 таблицы Т1 и Т2, строятся запросом Т1 и Т2.
Соответственно, если из Т1 в Т2 идет JOIN, то все таблицы, которые учавствуют в запросе Т2 (он тоже может быть составным), должны быть связаны таким же JOIN с Т1, так?

К сожалению, мы не можем получить результат запроса и передать его в фильтр по виртуальным таблицам. Поэтому отборы делаются через JOIN.

Приведу пример - если остатки выбираются через регистр остатков, а потом над ними выполняется еще один запрос (ну арифметика какая-нибудь - усреднение, например), то этот JOIN пойдет не только к таблице верхнего уровня (с арифметикой), но распространится и на исходную таблицу, которая выбирает остатки, т.е. с быстродействием должно быть все хоккей.
33 PVasili
 
04.08.06
12:07
(31)Хоть это радует, а то на 1C basic-е еще долго тра%:№"ь бы  :)
(32)А представь счастье, когда данные во view еще и обсчитываюся в sp на сервере :) (при том view не хранит данные а только алгоритм их расчета)
34 Гений 1С
 
гуру
04.08.06
12:07
Т.е. для програмиста виртуальные таблицы выглядят как плоские таблицы, с определенным набором полей. Он может связывать эти таблицы, объединяя их по одинаковым значениям полей (JOIN) или просто объединяя данные таблиц (UNION).

Т.е. он пишет примерно так.

Выбрать из Виртуальная1(параметры такие-то) JOIN Виртуальная2(параметры такие-то) ON "Товар","Склад"

Ну или в коде (Запрос-структура):
Новый Структура("Операция, Т1, Т2, П1, П2, Связь", "JOIN", "Виртуальная1", "Виртуальная2", Новый Структура(...), Новый Структура(...), "Товар, Склад")
35 Гений 1С
 
гуру
04.08.06
12:08
(33) 1С нужно в запросы просто добавить код курсоров и циклов, чтобы это все крутилось одинаково и на МС СКЛ и на Постгре.
36 Гений 1С
 
гуру
04.08.06
12:12
Возможно создать новый прикладной объект вью, где можно создавать запросы и хранимые процедуры, для которых будет составлен план запроса заранее, при старте конфы.
37 Гений 1С
 
гуру
04.08.06
12:13
А че, (32) дает нам классный движок...
38 прролдд
 
04.08.06
12:14
терзаниятупогоодинэсника
39 SnarkHunter
 
04.08.06
12:18
Это не терзания... Это какой-то поток сознания...
40 Гений 1С
 
гуру
04.08.06
12:19
(39) Гы, а истина то уже прощупалась, счас рожу
41 а лю 427
 
04.08.06
12:19
вообще то Гений у нас редкостный дятел... Опять изобретает велосипед с треугольными колесами...

P.S. а его идея называется в науке хранимыми процедурами, давно реализована в виде хранимых на сервере параметризованных процедур, которые вызываются с передачей параметров... но это не в среде 1С...

Если надо поменять логику запроса - он меняется только в одном месте - на сервере... можно менять прямо на ходу...

(39) какое сознание... туповатое
42 Гений 1С
 
гуру
04.08.06
12:25
(41) я знаю о хранимых процедураХ, это несколько другое
43 Гений 1С
 
гуру
04.08.06
12:25
(41) я даже их писал под SQL, веришь ли
44 Херрес
 
04.08.06
12:26
Ну так почему не юзать "настоящие" временные таблицы... в виде служебного справочника с табличными частями
45 PVasili
 
04.08.06
12:26
(41)почему дятел? ты не в теме....
Мысль правильная, дать пользователю возможность самому делать view и sp на сервере(хотя бы только на select). Ну и с учетом планов запросов и т.д.
46 PVasili
 
04.08.06
12:27
(44) это полумера
47 Гений 1С
 
гуру
04.08.06
12:27
Итак, каждая виртуальная таблица описывается:
•    Список колонок – список колонок в результате
•    Параметры – список параметров виртуальной таблицы
•    Код – код, который строит план запроса (через Выполнить)
При обращении к виртуальной таблице указывается:
•    Список колонок – список колонок, которые нужны в результате
•    Параметры – список параметров виртуальной таблицы
•    Соединение – с какой другой таблицей нужно соединить эту таблицу, по каким полям, слева или справа (JOIN)
•    Объединение – с какой другой таблицей нужно объединить результат таблицы (UNION)
Если таблица соединяется через JOIN, то этот JOIN транслируется на все вложенные запросы.
48 Гений 1С
 
гуру
04.08.06
12:30
Каждой виртуальной таблице присваивается уникальный идентификатор.
Может быть специальная виртуальная таблица для получения остатков по регистру накопления, например:
РегистрНакопления (ИмяРегистра, ДатаНачала, ДатаКонца и т.п.)

Т.е. запрос целиком будет состоять из обращения к виртуальным таблицам.
49 Гений 1С
 
гуру
04.08.06
12:31
И будет самооптимизирующемся за счет трансляции JOIN-ов от верхнего уровня к низу.
50 прролдд
 
04.08.06
12:35
(49) осталось только получить грант на развитие "1С:Предприятие 8.0".

Предлагаю наименование гранта: "Самореализация угнетенных программистских меньшинств", какие нибудь голубые пиндосы поведуться.
51 LoudMouth
 
04.08.06
12:45
Вам действительно занятся не чем.
52 Гений 1С
 
гуру
04.08.06
12:46
(51) ты не вкурил
53 PVasili
 
04.08.06
12:50
(52)гы-гы-гы половина видать не(или плохо) в теме и пытается острить :)
54 LoudMouth
 
04.08.06
12:56
(41)
55 а лю 427
 
04.08.06
13:01
(45)
"Мысль правильная, дать пользователю возможность самому делать view и sp на сервере(хотя бы только на select). Ну и с учетом планов запросов и т.д."


Еще адЫн птиц? этой системой воспользуется только один юзер из 10000, да и то только один раз... Остальные скажут - дай нам кнопочки.... ибо они - тупы...

P.S. Язык Sql запросов в свое время тоже придумали для того, чтобы юзер мог сам составлять запросы... Да вот только с тех пор чтото не видно юзеров, им пользующихся... в чистом виде...
56 AntonioS
 
04.08.06
13:04
не понимаю одного, зачем изобретать свой язык запросов, через структуры?
все уже придумано, до нас :)
хочешь свои вирутальные таблицы, так и пиши их в коде запроса, парси потом и подставляй текст подзапроса.
концепция сохраняется таким образом.
57 PVasili
 
04.08.06
13:10
(55)Ты сам птЫц. Не все же 1С ники тупы :). Есть и гении...
Если это на порядок(если не больше) увеличит скорость запросов почему не дать возможность людям(кто Асилит) это делать? Что сложно реализовать?(не думаю)
Почему все должены быть уперты в 1С basic? Как в анекдоте: "Если других машин не видеть то жигуль - кланая тачка..."

На 2 часть фразы ссылки... если частное мнение таки пиши...

(56)C виртуальными таблицами - полумера... хотя и на том спасибо :)
58 а лю 427
 
04.08.06
13:18
Скорость выполнения запросов или скорость написания запросов?

Скорость написания - это достигается другими средствами, доступными даже тупым одноЭсникам...
59 Гений 1С
 
гуру
04.08.06
13:24
(58) Какими? Построителями? гыгыгы...
Мой метод увеличит и скорость написания и скорость выполнения за счет оптимизации.
60 Tristan
 
04.08.06
13:32
(59) сначала надо худо бедно реализовать, а потом уже говорить, что "Мой метод увеличит и скорость написания и скорость выполнения за счет оптимизации", а пока это даже не на бумаге... нечего и утверждать.
Скорость выполнения "универсальных" вещей, как и типовых никогда не радовала, а вот отчеты под каждый регистр нудно, глупо и не красиво, но работают быстрее.
61 AntonioS
 
04.08.06
13:32
(59) мне вот интересно, ты видел сиквельный план запроса?
это по поводу распространения внешнего джойна на вложенные таблицы
62 Гений 1С
 
гуру
04.08.06
13:34
(61) видел, а что? Уточни...
(60) Но я думаю ТЗ я сочинил, реализовать - реализую, по мере возможности. А кто мешает тебе один раз прогнать эту шнягу, сохранить текст запроса - и вот он, вуаля, быстрый красавчик, сгенерированный программно
63 Tristan
 
04.08.06
13:35
(62) делай делай, потом посмотрим, а счас спорить о том конфетка или какашка получиться - бесполезно.
64 Гений 1С
 
гуру
04.08.06
13:52
По поводу JOIN задал вопрос v8: Знатокам по запросам.
65 AntonioS
 
04.08.06
13:55
(62) это по поводу (32) поста
66 Гений 1С
 
гуру
04.08.06
17:58
Вот что нагенерил мне конструктор моих запросов (первый блин):

ВЫБРАТЬ * ИЗ (ВЫБРАТЬ Псевдоним1.Ссылка КАК Договор ИЗ Справочник.Договоры КАК Псевдоним1) КАК З1 ПОЛНОЕ СОЕДИНЕНИЕ  (ВЫБРАТЬ Псевдоним2.Статус,Псевдоним2.Договор ИЗ РегистрСведений.Статусы.СрезПоследних(&Параметр1,(Истина))  КАК Псевдоним2) КАК З2 ПО З1.Договор=З2.Договор

А вот примерный код:

Функция обСписокВСтроку(СП, Разделитель=",") Экспорт
   Перем Рез;
   Рез="";
   Если ТипЗнч(СП)=Тип("Массив") Тогда
       Для Каждого Эл Из СП Цикл
           Рез=Рез+?(Рез="","",Разделитель)+Строка(Эл);        
       КонецЦикла;
   ИначеЕсли ТипЗнч(СП)=Тип("СписокЗначений") ИЛИ ТипЗнч(СП)=Тип("Структура") Тогда
       Для Каждого Эл Из СП Цикл
           Рез=Рез+?(Рез="","",Разделитель)+Строка(Эл.Значение);        
       КонецЦикла;
   КонецЕсли;
   Возврат Рез;    
КонецФункции

Функция обВТПолучитьИмяПараметра(П)
   Перем Н;
   обДоступСвойство(П, "НомерПараметра", Н);
   Н=Н+1;
   обДоступСвойствоУстановить(П, "НомерПараметра", Н);
   Возврат "Параметр"+Формат(Н, "ЧГ=");
КонецФункции

Функция обВТПолучитьИмяПсевдонима(П)
   Перем Н;
   обДоступСвойство(П, "НомерПсевдонима", Н);
   Н=Н+1;
   обДоступСвойствоУстановить(П, "НомерПсевдонима", Н);
   Возврат "Псевдоним"+Формат(Н, "ЧГ=");
КонецФункции

Функция обВТПолучитьСтрокуКолонок(П, Колонки)
   Перем ПсевдонимКолонки;
   Рез="";
   Для Каждого Эл Из Колонки Цикл
       Если Эл.Свойство("Псевдоним", ПсевдонимКолонки)=Неопределено Тогда
           ПсевдонимКолонки=Неопределено;
       КонецЕсли;
       Рез=Рез+?(Рез="","",",")+П.Псевдоним+"."+Эл.Имя+?(ПсевдонимКолонки=Неопределено, "", " КАК "+ПсевдонимКолонки);        
   КонецЦикла;
   Возврат Рез;
КонецФункции


Функция обВТУстановитьПараметр(П, Значение)
   Перем Запрос;
   ИмяПараметра=обВТПолучитьИмяПараметра(П);
   обДоступСвойство(П, "Запрос", Запрос);
   Запрос.УстановитьПараметр(ИмяПараметра, Значение);
   Возврат "&"+ИмяПараметра;
КонецФункции

Функция обВТУстановитьПсевдоним(П)
   Перем Псевдоним;
   Если П.Свойство("Псевдоним", Псевдоним) Тогда
       ИмяПсевдонима=Псевдоним;
   Иначе
       ИмяПсевдонима=обВТПолучитьИмяПсевдонима(П);
   КонецЕсли;
   П.Вставить("Псевдоним", ИмяПсевдонима);
   Возврат " КАК "+ИмяПсевдонима;
КонецФункции


//виртуальная таблица статусов договоров
//Идентификатор функции, колонки и параметры
Функция ВТСтатусДоговора(П)
   //Смотрим, какие колонки нужны
   Колонки=Новый Массив();
   Для Каждого Колонка из П.Колонки Цикл
       Если Колонка.Имя="Статус" ИЛИ Колонка.Имя="Договор" Тогда
           Колонки.Добавить(Колонка);
       КонецЕсли;
   КонецЦикла;
   
   //Параметры
   ПараметрПериод="";
   ПараметрУсловие="";
   ПараметрТип="";
   Если П.Свойство("Параметры") Тогда
       Если П.Параметры.Свойство("Период") Тогда
           ПараметрПериод=обВТУстановитьПараметр(П, П.Параметры.Период);
       КонецЕсли;
       Если П.Параметры.Свойство("Условие") Тогда
           ПараметрУсловие=П.Параметры.Условие;
       КонецЕсли;
       ПараметрУсловие=?(ПараметрУсловие="","(Истина)","("+ПараметрУсловие+")");
       Если П.Параметры.Свойство("Тип") Тогда
           ПараметрУсловие=ПараметрУсловие +" И (Договор ССЫЛКА "+П.Параметры.Тип+")";
       КонецЕсли;
       Если П.Параметры.Свойство("Статусы") И П.Параметры.Статусы<>Неопределено Тогда
           ПараметрУсловие=ПараметрУсловие +" И (Статус В ("+обВТУстановитьПараметр(П, П.Параметры.Статусы)+"))";
       КонецЕсли;
   КонецЕсли;
   Псевдоним=обВТУстановитьПсевдоним(П);
   Текст="ВЫБРАТЬ "+обВТПолучитьСтрокуКолонок(П, Колонки)+" ИЗ РегистрСведений.Статусы.СрезПоследних("+ПараметрПериод+","+ПараметрУсловие+") "+Псевдоним;
   П.Вставить("Текст", Текст);
КонецФункции

Функция ВТСправочник(П)
   Перем Вид, Колонки, Параметры;
   //обДоступСвойство(П, "Вид", Вид);
   //обДоступСвойство(П, "Колонки", Колонки);
   //обДоступСвойство(П, "Параметры", Параметры);
   Колонки=Новый Массив();
   
   МД=Метаданные.Справочники[П.Вид];
   Для Каждого Колонка из П.Колонки Цикл
       Если МД.Реквизиты.Найти(Колонка.Имя)<>Неопределено ИЛИ Колонка.Имя="Ссылка" Тогда
           Колонки.Добавить(Колонка);
       КонецЕсли;
   КонецЦикла;
   ПараметрУсловие="";
   
   Если П.Свойство("Параметры", Параметры) Тогда
       Для Каждого Параметр из Параметры Цикл
           Если Параметр.Имя="Условие" Тогда
               ПараметрУсловие=Параметр.Значение;
           КонецЕсли;
       КонецЦикла;
   КонецЕсли;
   
   Псевдоним=обВТУстановитьПсевдоним(П);
   
   Текст="ВЫБРАТЬ "+обВТПолучитьСтрокуКолонок(П, Колонки)+" ИЗ Справочник."+П.Вид+Псевдоним+
       ?(ПараметрУсловие="",""," ГДЕ "+ПараметрУсловие);
   П.Вставить("Текст", Текст);
КонецФункции


//Функция обДоступПрм(Родитель, Ребенок) Экспорт
//    Ребенок.Вставить("Родитель", Родитель);
//    Возврат Ребенок;
//КонецФункции



Функция ВТСправочникСНужнымСтатусом(П)
   Перем Параметры;
   //Формируем запрос по справочнику
   ПСправочник=Новый Структура("Вид, Колонки", П.Вид, П.Колонки);
   ВТСправочник(обДоступПрм(П, ПСправочник));
   
   флБезСтатуса=ложь;
   ПараметрСтатусы=Неопределено;
   
   Если П.Свойство("Параметры") Тогда
       Если П.Параметры.Свойство("БезСтатуса") И  П.Параметры.БезСтатуса=истина Тогда
           флБезСтатуса=истина;
       КонецЕсли;
   КонецЕсли;
   
   //Запрос по статусам договоров
   ПСтатусы=Новый Структура("Тип,Колонки", "Справочник."+П.Вид, П.Колонки);
   Если П.Свойство("Параметры") Тогда
       ПСтатусы.Вставить("Параметры", П.Параметры);
   КонецЕсли;
   
   //Если договор без статуса, тогда
   Если флБезСтатуса Тогда
       ПСтатусы.Вставить("Статусы", Неопределено);
   КонецЕсли;
   
   ВТСтатусДоговора(обДоступПрм(П, ПСтатусы));
   
   //Объединяем
   Если флБезСтатуса Тогда
       Текст="ВЫБРАТЬ * ИЗ #ЗапросСправочник ЛЕВОЕ СОЕДИНЕНИЕ  #ЗапросСтатусы ПО #Справочник.Ссылка=#Статусы.Договор
           | И (#Статусы.Договор = NULL ИЛИ #УсловиеСтатусов";
       Если П.Свойство("Параметры") И П.Параметры.Свойство("Статусы") Тогда
           УсловиеСтатусов="Статусы.Статус В (#ПараметрСтатусы))";
           УсловиеСтатусов=СтрЗаменить(УсловиеСтатусов, "#ПараметрСтатусы", обВТУстановитьПараметр(П, П.Параметры.Статусы));
       Иначе
           УсловиеСтатусов="ИСТИНА";
       КонецЕсли;
       Текст=СтрЗаменить(Текст, "#УсловиеСтатусов",  УсловиеСтатусов);
   Иначе
       Текст="ВЫБРАТЬ * ИЗ (#ЗапросСправочник) КАК З1 ПОЛНОЕ СОЕДИНЕНИЕ  (#ЗапросСтатусы) КАК З2 ПО З1.Договор=З2.Договор";
   КонецЕсли;
   Текст=СтрЗаменить(Текст, "#ЗапросСправочник", ПСправочник.Текст);
   Текст=СтрЗаменить(Текст, "#ЗапросСтатусы", ПСтатусы.Текст);
   Текст=СтрЗаменить(Текст, "#Справочник", ПСправочник.Псевдоним);
   Текст=СтрЗаменить(Текст, "#Статусы", ПСтатусы.Псевдоним);
   
   П.Вставить("Текст", Текст);
КонецФункции



Функция обВТЗапрос()
   П=Новый Структура();
   Запрос=Новый Запрос();
   П.Вставить("Запрос", Запрос);
   Колонки=Новый Массив();
   П.Вставить("Колонки", Колонки);
   П.Вставить("Параметры", Новый Структура());
   П.Вставить("НомерПсевдонима", 0);
   П.Вставить("НомерПараметра", 0);
   Возврат П;
КонецФункции


Процедура КнопкаВыполнитьНажатие(Кнопка)
   // Вставить содержимое обработчика.
   //Запрос, который извлекает договоры, которые были закрыты только
   П=обВТЗапрос();
   П.Колонки.Добавить(Новый Структура("Имя,Псевдоним", "Ссылка","Договор"));
   П.Колонки.Добавить(Новый Структура("Имя", "Статус"));
   П.Колонки.Добавить(Новый Структура("Имя", "Договор"));
   
   П.Параметры.Вставить("Период", ТекущаяДата());
   
   П.Вставить("Вид", "Договоры");

   ВТСправочникСНужнымСтатусом(П);
   П.Запрос.Текст=П.Текст;
   Сообщить(П.Запрос.Текст);
   //Результат=П.Запрос.Выполнить();
   //Результат.Выгрузить().ВыбратьСтроку("Запрос 1");
КонецПроцедуры