Отношение "Многие ко многим" в запросе динамического списка.

1. BuryMeInVegas 16.06.21 10:42 Сейчас в теме
Доброго времени суток! Имеется задача: на форму списка документа вывести колонку, в которой лежит подчиненный документ. Факт: подчинённых документов у исходного может быть n штук. Не менее шокирующий факт: у подчиненных документов может быть n исходных документов. Итого имеется связь многие ко многим. Первый момент легко исправляется тем, что нам не нужна ссылка на подчиненный документ и нам достаточно взять номер дочернего дока. Проблема заключается в том, что ссылка на документ-родитель нам нужна, и она ввиду такой связи замножается, от чего динамический список периодически ломается.

На всякий случай приложу запрос, где попытался решить эту проблему, но безуспешно:
|ВЫБРАТЬ РАЗЛИЧНЫЕ
|	док.Ссылка,
|	док.ПометкаУдаления,
|	док.Номер,
|	док.Дата,
|	док.Проведен,
|	док.ЗаявочнаяКампания КАК Год,
|	док.Сумма,
|	док.Ответственный,
|	ВЫРАЗИТЬ(док.Комментарий КАК СТРОКА(1000)) КАК Комментарий,
|	док.МоментВремени,
|	док.НомерДок,
|	док.СпособЗакупки,
|	ВЫБОР
|		КОГДА э_СтатусыДокументов.СтатусОбъекта = ЗНАЧЕНИЕ(Справочник.э_СтатусыДокументов.Редактируется)
|			ТОГДА 0
|		КОГДА э_СтатусыДокументов.СтатусОбъекта = ЗНАЧЕНИЕ(Справочник.э_СтатусыДокументов.НаСогласовании)
|			ТОГДА 1
|		КОГДА э_СтатусыДокументов.СтатусОбъекта = ЗНАЧЕНИЕ(Справочник.э_СтатусыДокументов.Утвержден)
|			ТОГДА 2
|		КОГДА э_СтатусыДокументов.СтатусОбъекта = ЗНАЧЕНИЕ(Справочник.э_СтатусыДокументов.Отказ)
|			ТОГДА 3
|		ИНАЧЕ 55
|	КОНЕЦ КАК НомерСтатуса,
|	э_СтатусыДокументов.Состояние,
|	ВЫБОР
|		КОГДА док.Сумма < 500000
|			ТОГДА ЛОЖЬ
|		ИНАЧЕ ИСТИНА
|	КОНЕЦ КАК ОС,
|	э_СтатусыДокументов.СтатусОбъекта КАК Статус,
|	док.ПредметДоговора,
|	док.Ответственный.ТекущееПодразделение,
|	ЕСТЬNULL(м12_СуммыРаспределенийОбороты.СуммаОборот, 0) КАК СуммаРаспределений,
|	ВложенныйЗапрос.ПодчиненныйДокумент
|ИЗ
|	Документ.м12_ППЗ КАК док
|		ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.э_СтатусыДокументов КАК э_СтатусыДокументов
|		ПО док.Ссылка = э_СтатусыДокументов.Документ
|		ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.м12_СуммыРаспределений.Обороты КАК м12_СуммыРаспределенийОбороты
|		ПО док.Ссылка = м12_СуммыРаспределенийОбороты.ГлавныйДокумент
|		ЛЕВОЕ СОЕДИНЕНИЕ (ВЫБРАТЬ ПЕРВЫЕ 1
|			м12_СвязанныеДокументы.ДокументИсточник КАК ДокументИсточник,
|			"Детализированная ППЗ №" + м12_СвязанныеДокументы.ПодчиненныйДокумент.НомерДок КАК ПодчиненныйДокумент,
|			МИНИМУМ(м12_СвязанныеДокументы.ПодчиненныйДокумент.Дата) КАК ПодчиненныйДокументДата
|		ИЗ
|			РегистрСведений.м12_СвязанныеДокументы КАК м12_СвязанныеДокументы
|		ГДЕ
|			м12_СвязанныеДокументы.ДокументИсточник ССЫЛКА Документ.м12_ППЗ
|			И м12_СвязанныеДокументы.ПодчиненныйДокумент ССЫЛКА Документ.э_ПозицияПЗ
|		
|		СГРУППИРОВАТЬ ПО
|			м12_СвязанныеДокументы.ДокументИсточник,
|			"Детализированная ППЗ №" + м12_СвязанныеДокументы.ПодчиненныйДокумент.НомерДок) КАК ВложенныйЗапрос
|		ПО док.Ссылка = ВложенныйЗапрос.ДокументИсточник
|{ГДЕ
|	(док.СпособЗакупки В (&СпособЗакупки))}
Показать


Прошу к архитектуре сильно не привязываться, я сам бесконечно благодарен тем людям, кто заложил подобную логику подчиненности документов. :) Ну и заранее благодарю за ответы!
По теме из базы знаний
Ответы
Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
2. SlavaKron 16.06.21 10:59 Сейчас в теме
(1) Я бы рекомендовал выводить данные подчиненных документов и любых других, которые множат Ссылку основной таблицы, в событии динамического списка ПриПолученииДанныхНаСервере.
3. BuryMeInVegas 16.06.21 11:00 Сейчас в теме
(2) С Вашей точки зрения, делать это одним запросом динамического списка не получится?
4. SlavaKron 16.06.21 11:04 Сейчас в теме
(3) Может и получится, но это сложнее в реализации и в итоге, скорее всего получится монстр-запрос.
5. BuryMeInVegas 16.06.21 11:06 Сейчас в теме
(4) Не очень хочу делать два исполнения запроса к БД при открытии формы.) Система и так крайне не оптимизирована, есть желание как можно меньше насиловать сервер БД.))
6. SlavaKron 16.06.21 11:10 Сейчас в теме
(5) При прокрутке списка в ПриПолученииДанныхНаСервере передается лишь список ссылок, для которых нужно обновить оформление. Если запрос сделать простым и плоским с последующей обработкой результата и заполнением оформление, то должно работать шустро.
7. BuryMeInVegas 16.06.21 11:11 Сейчас в теме
(6) Понял, попробую пошаманить. Но в случае возникновения проблем Вы будете первым, кто об этом узнает. ;)
8. BuryMeInVegas 16.06.21 14:21 Сейчас в теме
(6) Ну вот и вопрос: для использования
Строки.ПолучитьКлючи()
необходимо, чтобы в запросе динамического списка мы получали только одно поле ссылочного типа?

UPD. Не задавал бы такой наивный вопрос, если бы отладчик залетал в СписокПриПолученииДанныхНаСервере(), но увы.
9. SlavaKron 16.06.21 14:24 Сейчас в теме
(8) Вовсе нет. Будет получен массив ссылок основной таблицы динамического списка и от текста запроса он не зависит.
10. BuryMeInVegas 16.06.21 14:25 Сейчас в теме
(9) Т.е. условно, в массив попадут ссылки на документ, справочник, перечисление и т.д., который потом я передаю параметром в запрос. Верно понимаю?

UPD. В зависимости от того, какой набор ссылок вернётся в запросе.
11. SlavaKron 16.06.21 14:29 Сейчас в теме
(10) Я, видимо, неправильно понял предыдущий вопрос. Строки.ПолучитьКлючи() вернёт массив ссылок, только с типом документа динамического списка. Далее вы вольны делать с этим массивом что угодно. Да, обычно используют в запросе в качестве параметра, чтобы вытащить связанные данные, которые проблематично получить в запросе динамического списка.
12. BuryMeInVegas 16.06.21 14:32 Сейчас в теме
(11) Вот мне и интересно, в случае, если у нас, например, на форме списка есть дин. список, в строке которого содержится как ссылка на нужный нам документ, так, например, и любое другое поле, со ссылкой, например, на справочник, в массив залетят только лишь прямые ссылки на документ?
13. SlavaKron 16.06.21 14:36 Сейчас в теме
(12) Да. Но суть в том, что в запросе достаточно "застолбить" поля под дополнительные данные. В самом тексте запроса ДС данные, которые вы будете получать в ПриПолученииДанныхНаСервере получать не нужно. Например
ВЫРАЗИТЬ("" КАК СТРОКА(200)) КАК НомераПодчиненныхДокументов,
14. BuryMeInVegas 16.06.21 14:39 Сейчас в теме
(13)
Например
ВЫРАЗИТЬ("" КАК СТРОКА(200)) КАК НомераПодчиненныхДокументов
Это я понял, так и делаю. Пытаюсь выяснить, почему не заполняется необходимое мне поле, ибо запрос, которым я его хочу заполнять, в консольке отрабатывает, как часы. Именно исходя из этого факта я делаю вывод, что в параметр запроса как-то криво садятся данные.

UPD. Будто бы передаётся либо пустой массив, либо вообще не ссылки на интересующий меня документ. Впрочем, совершенно забыл про
Сообщить()
, сейчас гляну, как массив заполнился.))
15. SlavaKron 16.06.21 14:50 Сейчас в теме
Структура кода примерно такая:
&НаСервереБезКонтекста
Процедура СписокПриПолученииДанныхНаСервере(ИмяЭлемента, Настройки, Строки)	
	
	// проверка выведено ли поле на форму
	Для Каждого КлючИЗначение Из Строки Цикл 
		Если Не КлючИЗначение.Значение.Данные.Свойство("СуммаВЦенахПродажи") Тогда
			Возврат
		КонецЕсли;
		Прервать;
	КонецЦикла; 
	
	МассивСсылок = Новый Массив;
	СтрокиДС = Новый Соответствие;
	Для Каждого КлючИЗначение Из Строки Цикл 
		СсылкаНаДокумент = КлючИЗначение.Ключ.Ссылка;
		МассивСсылок.Добавить(СсылкаНаДокумент);
		СтрокиДС.Вставить(СсылкаНаДокумент, КлючИЗначение.Значение); 
	КонецЦикла;
	
	Запрос = Новый Запрос
	// текст запроса, для получения дополнительных данных чего-либо
	
	Запрос.УстановитьПараметр("МассивСсылок", МассивСсылок);
	Выборка = Запрос.Выполнить().Выбрать();
	
	Пока Выборка.Следующий() Цикл
		СтрокаСписка = СтрокиДС[Выборка.Ссылка];
		СтрокаСписка.Данные.СуммаВЦенахПродажи = Формат(Выборка.Сумма, "ЧДЦ=2");
	КонецЦикла;
	
КонецПроцедуры
Показать
16. BuryMeInVegas 16.06.21 14:52 Сейчас в теме
(15) Делаю вот так по примеру с its
&НаСервереБезКонтекста
Процедура СписокПриПолученииДанныхНаСервере(ИмяЭлемента, Настройки, Строки)
	
	Запрос = Новый Запрос("ВЫБРАТЬ
	                      |	м12_СвязанныеДокументы.ДокументИсточник,
	                      |	МИНИМУМ(м12_СвязанныеДокументы.ПодчиненныйДокумент.Дата) КАК ПодчиненныйДокументДата
	                      |ПОМЕСТИТЬ ВТ_ПолучитьПодчинённые
	                      |ИЗ
	                      |	РегистрСведений.м12_СвязанныеДокументы КАК м12_СвязанныеДокументы
	                      |ГДЕ
	                      |	м12_СвязанныеДокументы.ДокументИсточник ССЫЛКА Документ.м12_ППЗ
	                      |	И м12_СвязанныеДокументы.ПодчиненныйДокумент ССЫЛКА Документ.э_ПозицияПЗ
	                      |
	                      |СГРУППИРОВАТЬ ПО
	                      |	м12_СвязанныеДокументы.ДокументИсточник
	                      |;
	                      |
	                      |////////////////////////////////////////////////////////////­////////////////////
	                      |ВЫБРАТЬ
	                      |	ВТ_ПолучитьПодчинённые.ДокументИсточник,
	                      |	""Детализированная ППЗ №"" + э_ПозицияПЗДокументыППЗ.Ссылка.НомерДок КАК ПодчиненныйДокумент
	                      |ПОМЕСТИТЬ ВТ_ПерваяДППЗ
	                      |ИЗ
	                      |	ВТ_ПолучитьПодчинённые КАК ВТ_ПолучитьПодчинённые
	                      |		ЛЕВОЕ СОЕДИНЕНИЕ Документ.э_ПозицияПЗ.ДокументыППЗ КАК э_ПозицияПЗДокументыППЗ
	                      |		ПО ВТ_ПолучитьПодчинённые.ДокументИсточник = э_ПозицияПЗДокументыППЗ.ДокументППЗ
	                      |			И ВТ_ПолучитьПодчинённые.ПодчиненныйДокументДата = э_ПозицияПЗДокументыППЗ.Ссылка.Дата
	                      |;
	                      |
	                      |////////////////////////////////////////////////////////////­////////////////////
	                      |ВЫБРАТЬ
	                      |	м12_ППЗ.Ссылка,
	                      |	ВТ_ПерваяДППЗ.ПодчиненныйДокумент
	                      |ИЗ
	                      |	Документ.м12_ППЗ КАК м12_ППЗ
	                      |		ЛЕВОЕ СОЕДИНЕНИЕ ВТ_ПерваяДППЗ КАК ВТ_ПерваяДППЗ
	                      |		ПО м12_ППЗ.Ссылка = ВТ_ПерваяДППЗ.ДокументИсточник
	                      |ГДЕ
	                      |	м12_ППЗ.Ссылка В(&ДинамическийСписокППЗ)");
	
	Запрос.УстановитьПараметр("ДинамическийСписокППЗ", Строки.ПолучитьКлючи());
	Выборка = Запрос.Выполнить().Выбрать();
	
	Пока Выборка.Следующий() Цикл
		СтрокаСписка = Строки[Выборка.Ссылка];
		СтрокаСписка.Данные["ПодчиненныйДокумент"] = Выборка.ПодчиненныйДокумент;
	КонецЦикла;
	
	Для каждого Ссылка Из Строки.ПолучитьКлючи() Цикл
	
		Сообщить(Строка(Ссылка));
	
	КонецЦикла;
	
КонецПроцедуры
Показать


UPD. "Сообщить()" вывел для отладки.
17. SlavaKron 16.06.21 15:06 Сейчас в теме
(16) Тут проблемы с запросом. Массив ссылок будет содержать не больше 2-3 десятков элементов, то есть довольно немного, а во временной таблице у вас нигде нет ограничений на выборку по параметру &ДинамическийСписокППЗ.
18. BuryMeInVegas 16.06.21 15:08 Сейчас в теме
(17) Не совсем понимаю. Я наложил этот параметр в финальной выборке, в любом случае, в запрос должны улететь эти ссылки. Опять же, запрос в консоли запросов работает, как часы.
19. SlavaKron 16.06.21 15:18 Сейчас в теме
(18) Я про то, что он не оптимален. ВТ создается по всем ссылкам. Теряется смысл в порционности. Размер ВТ может сильно замедлять производительность системы.
20. BuryMeInVegas 16.06.21 15:24 Сейчас в теме
(19) Я с удовольствием его оптимизирую в тот самый момент, когда получу интересующие меня данные в поле динамического списка.))

Это же не финальный вариант, а тот, который должен показать мне, что всё ок, можно доводить до ума. А в данный момент я ну никак не могу понять, почему либо не формируется массив ссылок на нужный мне документ, либо криво передаётся в параметр запроса.
21. SlavaKron 16.06.21 15:30 Сейчас в теме
(20)
не формируется массив ссылок
Попробуйте собрать массив ссылок, как это сделано в (15).
22. BuryMeInVegas 17.06.21 09:26 Сейчас в теме
(21) Короче говоря, на платформе заказчика эта процедура просто не работает, поэтому и отладчик туда не влетает. Решил задачу супер не оптимально, но деваться некуда. А Вас благодарю за ответ!
Оставьте свое сообщение

Для получения уведомлений об ответах подключите телеграм бот:
Инфостарт бот