Форум Кладовочки АЛьФ`а

Общие вопросы => 7.7 => Тема начата: Злоп от 24 мая 2025, 20:43

Название: МФ и SQL - как обойти кривую выдачу
Отправлено: Злоп от 24 мая 2025, 20:43
Как известно (?) штатный МФ на SQL отрабатывает криво.
Кто как это обходит (без классов желательно, штатными средствами).

По факту получается что условия МФ вида (штано)
Условие(Контрагент в глУсловие1)приходится заменять на
Условие(глУсловие1.Принадлежит(Контрагент)=1)
Есть какие-то другие варианты?
Название: Re: МФ и SQL - как обойти кривую выдачу
Отправлено: Злоп от 24 мая 2025, 23:18
.. и что-то "потерялся" я в каких случаях МФ на SQL косячит.
Вроде был года в МФ условие "одно из " и в списке - всего одна группа...? Сейчас проверяю - вроде норм работает...
Когда МФ типовой на SQL косячит?
Название: Re: МФ и SQL - как обойти кривую выдачу
Отправлено: Злоп от 25 мая 2025, 02:20
Собственно описано здесь для Uchoice
https://infostart.ru/1c/articles/68332/

Для типового использования МФ во всяких отчетах (с закладкой МФ которые) в ГМ меняем
а процедуре глФильтрПоСправочнику

        // Если ЕстьМФ = 1 Тогда // есть множественный фильтр по позициям справочника
// Если ТипМФ=1 Тогда // принадлежит списку
// ТекстЗапроса = ТекстЗапроса+РазделительСтрок+"Условие("+ИмяПеремЗапроса+" в "+ИмяПоляМФ+");";
// Иначе     
// ТекстЗапроса = ТекстЗапроса+РазделительСтрок+"Условие(НЕ("+ИмяПеремЗапроса+" в "+ИмяПоляМФ+"));";
// КонецЕсли;
// КонецЕсли;
//
// Если ЕстьЕФ = 1 Тогда // есть простой фильтр по позициям справочника
// ТекстЗапроса= ТекстЗапроса+РазделительСтрок+"Условие("+ИмяПеремЗапроса+" в "+ИмяПоляЕФ+");";
// КонецЕсли;
// -------- заменено на: -----------------------------------------------------------------------------------------------------
// для SQL условие в СЗ работает плохо
Если ЕстьМФ = 1 Тогда // есть множественный фильтр по позициям справочника
Если ТипМФ=1
Тогда // принадлежит списку
ТекстЗапроса = ТекстЗапроса+РазделительСтрок+"Условие("+ИмяПоляМФ+".Принадлежит("+ИмяПеремЗапроса+")=1);";
Иначе // не принадлежит списку     
ТекстЗапроса = ТекстЗапроса+РазделительСтрок+"Условие("+ИмяПоляМФ+".Принадлежит("+ИмяПеремЗапроса+")=0);";
КонецЕсли;
КонецЕсли;

Если ЕстьЕФ = 1 Тогда // есть простой фильтр по позициям справочника
Если ПолеЕФ.ЭтоГруппа()=0
Тогда // элемент справочника
ТекстЗапроса= ТекстЗапроса+РазделительСтрок+"Условие("+ИмяПеремЗапроса+" в "+ИмяПоляЕФ+");";
Иначе // группа справочника
ТекстЗапроса = ТекстЗапроса+РазделительСтрок+"Условие("+ИмяПеремЗапроса+".ПринадлежитГруппе("+ИмяПоляЕФ+")=1);";
КонецЕсли;
КонецЕсли;
Название: Re: МФ и SQL - как обойти кривую выдачу
Отправлено: Злоп от 25 мая 2025, 02:27
Можно в ГМ процедуры работы не править,
а добавить еще одну процедуру, в которой перед выполнением запроса для SQL версии заменять в текстовке запроса "неправильные" условия на "правильные"...
Название: Re: МФ и SQL - как обойти кривую выдачу
Отправлено: Злоп от 25 мая 2025, 02:28
Но все это как-то неаккуратненько, но другого варианта, обойтись штатными возможностями, наверное, нет?
Название: Re: МФ и SQL - как обойти кривую выдачу
Отправлено: Харлампий Дымба от 25 мая 2025, 19:07
Цитата: Злоп от 25 мая 2025, 02:20Собственно описано здесь для Uchoice
https://infostart.ru/1c/articles/68332/ (https://infostart.ru/1c/articles/68332/)
Что-то не доверяю я. Запрос действительно не работает в SQL и работает в DBF.
Но вот что ошибка должна называться именно "одна группа в списке" - сомневаюсь. Потому что две группы тоже не работают :)
Просто там запрос реально кривой.
Вместо
    ТекстЗапроса = "
    |ПеремОбъект = Справочник.Контрагенты.ТекущийЭлемент;
    |Группировка ПеремОбъект Без Групп;
    |Перем1 = Справочник.Контрагенты.Родитель;
    |Условие (Перем1 В гУсл1);
    |";
Должно быть
    ТекстЗапроса = "
    |ПеремОбъект = Справочник.Контрагенты.ТекущийЭлемент;
    |Группировка ПеремОбъект Без Групп;
    |Условие (ПеремОбъект В гУсл1);
    |";
И никаких проблем с одной группой в списке - всё отрабатывает нормально. Возможно корни ошибки всё-таки не в "одна группа в списке", а именно в .Родитель. Потому что-то тот же запрос но в виде
    ТекстЗапроса = "
    |ПеремОбъект = Справочник.Контрагенты.ТекущийЭлемент;
    |Группировка ПеремОбъект Без Групп;
    |Перем1 = Справочник.Контрагенты.ОтветственныйМенеджер;
    |Условие (Перем1 В гУсл1);
где отбор идёт по группе менеджеров - нормально отрабатол в SQL.
Название: Re: МФ и SQL - как обойти кривую выдачу
Отправлено: Харлампий Дымба от 25 мая 2025, 20:41
Посмотри, потому что Принадлежит( и ПринадлежитГруппе( это прям серьёзное замедление относительно использования элементарного условия с "В".
Не наблюдаю проблем с использованием группы в списке ни в SQL, ни в DBF. Понятно, что в UChoice.ert мог быть неудачный код, но зачем же всё остальное работающее из-за этого ломать? REfPrint.ert тоже при некоторых комбинациях  в ошибку вываливается, но платформа тут ни при чём.

Название: Re: МФ и SQL - как обойти кривую выдачу
Отправлено: Злоп от 26 мая 2025, 00:14
 Требуются более детальные исследования.
Условие с переменной, которая . Родитель - достаточно искусственный пример.
.
Надо внимательнее посмотреть.
Возможно на разных SQL по разному отрабатывает.
.
Повнимательнее смотреть на полный текст запроса когда запрос не срабатывает.
.
Надо исследовать. Когда время будет.
А сейчас задача - чтобы возвращался правильный результат. Медленно или быстро - уже второй вопрос.
Название: Re: МФ и SQL - как обойти кривую выдачу
Отправлено: Харлампий Дымба от 26 мая 2025, 01:10
Так дело в том, что отбор по списку из одной группы работает в типовых и в SQL, и в DBF. Мифичиская "ошибка" взялась из-за единичного криво написанного запроса: попытка сделать запрос универсальным конструктором привела к корявенькому тексту запроса с .Родитель, который в SQL не отрабатывает (странно, что он вообще отрабатывает в DBF). И это исключительно в UChoice.ert (в типовой ТиС она включена под названием Обработка.ПодборОбъектов - по кнопочке <?> в множественных фильтрах отчетов). И исправление нужно только для этой обработки,  которая никаких глобальных функций не трогает. Так что это вполне сойдёт за ошибку типовой ТиС (https://forum.dorex.pro/index.php?topic=254.0).
Я почему это всё пишу - просто когда осадочек остаётся, потом начинаешь сильно перестраховываться в тех местах, где это совсем не надо. Плюс без надобности сильно замедлять формирование запросов: если есть условия с вызовом функций языка (не элементарные), запросы будут выполняться знаааачительно медленнее. Вот только что в https://forum.dorex.pro/index.php?topic=257.15 паровоз из нескольких десятков ИЛИ в условии снаряжал, чтобы избежать НайтиЗначение и Принадлежит.
А разбираться да, некогда обычно)


Название: Re: МФ и SQL - как обойти кривую выдачу
Отправлено: Злоп от 26 мая 2025, 01:23
то бишь
Условие(Элемент в СЗ) - где Элемент есть переменная запроса, отработает правильно в любом варианте состава СЗ, в СЗ может быть и одна группа, и один элемент и смесь элементов и групп и много групп) - так?
а
Условие(Группа в СЗ) - где Группа есть переменная запроса - скосячит, так?

При этом
Условие(Элемент в ВыбНоменклатура) - где ВыбНоменклатура есть либо элемент, либо группа - отработает норм?
Условие(Группа в ВыбНоменклатура) - отработает норм?
Название: Re: МФ и SQL - как обойти кривую выдачу
Отправлено: Харлампий Дымба от 26 мая 2025, 03:31
Если речь про справочники, то:

Не стоит делать так (1):
Группа = Справочник.Контрагенты.Родитель;
Условие(Группа в СписокГрупп);
И не стоит делать так (2):
Элемент = Справочник.Контрагенты.ТекущийЭлемент;
Условие(Элемент.Группа в СписокГрупп);
Стоит делать так (3):
Элемент = Справочник.Контрагенты.ТекущийЭлемент;
Условие(Элемент в СписокГруппИНеТолько);

Я просто пытался сместить фокус - проблема не в каких-то пресловутых группах в списке значений, а в использовании группы в качестве переменной запроса - а такого не должно быть в нормальном запросе.
Если есть ИТС, то можно почитать здесь: https://its.1c.ru/db/metod77#content:2147484625:hdoc . Своими словами: при обработке справочника группы справочника не обрабатываются. Они обрабатываются при постобработке уже полученных записей для построения иерархии. Запросом нельзя обработать "только группы" или "все-все элементы и группы" (группы без элементов запросом не получить, также как и группы, чьи элементы не прошли отбор по условиям).
Иллюстрация для размышления:
ТекстЗапроса =
"//{{ЗАПРОС(Сформировать)
|Контрагент = Справочник.Контрагенты.ТекущийЭлемент;
|Группировка Контрагент ;
|Условие (Контрагент.ЭтоГруппа()=1);
|"//}}ЗАПРОС
;
всегда будет пустой, хотя казалось бы: должен показать группы контрагентов.

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

Название: Re: МФ и SQL - как обойти кривую выдачу
Отправлено: Злоп от 26 мая 2025, 23:01
Спасибо за пояснения.
Учту, переделаю, проверю.
Название: Re: МФ и SQL - как обойти кривую выдачу
Отправлено: Djelf от 27 мая 2025, 15:56
Ужос, нах...
Перепишите на класс ПрямойЗапрос, ну сожрет он 300мс (на трансформацию запроса в sql), это что проблема?
На мелких запросах совсем чуток, но я запросил и разработчик сделал метод получить Совсем прямой запрос (читайте мануаль), т.е. после обработки парсером, это работает значительно лучше, для запросов, которые требуют минимального отклика.

P.S.
Там все уже устарело, и в mssql и sqlite многое можно реализовать более эффективно - табличными, рекурсивными функциями и т.п.
И! Я не пользуюсь этим классом, мне вопросы типа "как ускорить" постить не надо.
Название: Re: МФ и SQL - как обойти кривую выдачу
Отправлено: Харлампий Дымба от 27 мая 2025, 19:10
Я не знаю, что у Злопа. Про себя я писал: основная работа: компоненты "Бухгалтерский учет" и "Расчет". Всё DBF. Никаких регистров и никаких высоконагруженных систем. Даже регистры не мог себе позволить использовать.
+2 ларька на торговле DBF не стоили того, чтобы переписывать ТиС.
+1 нормальный клиент на переписанной комплексной SQL - где-то на периферии основной работы, жужжит и не требует особого внимания.
Пока уважаемые люди ускоряли свои высоконагруженные системы  в SQL не вылезая с 1cpp.ru , я ковырял Зарплату и кадры. Ну никаким боком мне прямые запросы в моих конфах не заходили.
TurboBL- хорошая штука, зря пропустил - хорошее ускорение задаром.
Всё остальное у меня - как правило: 10% время на запрос, 90% на "ВывестиСекцию()".В лучшем случае журнал проводок не за 5 секунд будет формироваться, а за 4.8. И то не факт, что у меня в обозримом будущем получится это корректно сделать. А текущей срочной работы - как минимум на полгода вперед.

Ну и просто:
в типовой ТиС 1011 - 241  запрос, 190 ВыбратьЭлементы, 60 ВыбратьДокументы, 39 ВыбратьПодчиненныеДокументы, плюс обвязка всякая.
Наверное, Сергей со временем всё это перепишет (или уже переписал) и во все ларьки поставит SQL,  но до тех пор - пусть у него не будет ненужной заплатки, там где она не нужна. Если не использовать точку в условиях черного запроса, то может и прямые не понадобятся. ;)
Название: Re: МФ и SQL - как обойти кривую выдачу
Отправлено: Злоп от 27 мая 2025, 20:31
У меня как у Харлампия.
Прямые запросы - там где реально клинит.
Не имеет смысла для жабодавных клиентов тратить время на освоение прямых. Самые простенькие прямые я смогу написать.
.
Я скорее прямые освою как хобби от нечего делать чем для клиентов.
Название: Re: МФ и SQL - как обойти кривую выдачу
Отправлено: Arbuz от 30 мая 2025, 15:05
Хм, ну вот, например, в ТиС в документе списание, ускорение в несколько тысяч раз, вместо десятков секунд — сотни миллисекунд:
//******************************************************************************
// ЗаполнениеПоДокументуОснованию()
//
// Параметры:
//  Нет
//
// Возвращаемое значение:
//  Нет
//
// Вызывается из формул элементов диалога:
//
// Описание:
//  Производит заполнение документа по документу  - основанию.
//
Функция ЗаполнениеПоДокументуОснованию()
Перем СписанныеКоличества;

Если ДокОснование.Выбран()=0 Тогда
Возврат "Документ - основание не выбран!";
КонецЕсли;

Если (ДокОснование.Вид() <> "ИнвентаризацияТМЦ") Тогда
Возврат "Неверный вид документа - основания!";
КонецЕсли; // вид ДокОснования

// сформируем список товаров,
//{[*]Arbuz, 28.06.2021 14:02:53
// ТекстЗапроса = "//{{ЗАПРОС(ПредСписание)
// |Период с '01.01.1980' по ДатаДок;
// |Без итогов;
// |Основание = Документ.СписаниеТМЦ.ДокОснование, Документ.Реализация.ДокОснование, Документ.ОтчетККМ.ДокОснование, Документ.РеализацияРозница.ДокОснование;
// |Товар = Документ.СписаниеТМЦ.Номенклатура, Документ.Реализация.Номенклатура, Документ.ОтчетККМ.Номенклатура, Документ.РеализацияРозница.Номенклатура;
// |Колво = Документ.СписаниеТМЦ.Количество, Документ.Реализация.Количество, Документ.ОтчетККМ.Количество, Документ.РеализацияРозница.Количество;
// |Коэфф = Документ.СписаниеТМЦ.Коэффициент, Документ.Реализация.Коэффициент, Документ.ОтчетККМ.Коэффициент, Документ.РеализацияРозница.Коэффициент;
// |Функция ВсегоКолво = Сумма(Колво);
// |Группировка Товар без групп;
// |Группировка Коэфф;
// |Условие(Основание = ДокОснование);
// |"//}}ЗАПРОС
// ;
// _ф = _GetPerformanceCounter(); //[+]Arbuz, 28.06.2021 13:46:48
//
// Запрос = СоздатьОбъект("Запрос");
// Если Запрос.Выполнить(ТекстЗапроса) = 0 Тогда
// Возврат "Ошибка при отборе товаров.";
// КонецЕсли;
//
// глОтладка("Чёрный " + (_GetPerformanceCounter() - _ф)); //[+]Arbuz, 28.06.2021 13:46:53
//
// Запрос.Выгрузить(СписанныеКоличества, 1, 0);
//
// глОтладка(СписанныеКоличества, 3); //[+]Arbuz, 28.06.2021 13:45:10
// -------------^^^===vvv-------------
ТекстЗапроса = "
|--EXPLAIN QUERY PLAN
|SELECT
|-- Товары.Документ [Основание :Документ]
| Товары.Товар [Товар :Справочник.Номенклатура]
| ,Товары.Коэфф
| ,SUM(Товары.Колво) ВсегоКолво
|FROM (
| SELECT
|-- Документы.Документ_вид||Документы.Документ Документ
| COALESCE(
| СписаниеТМЦ.Номенклатура
| ,Реализация.Номенклатура
| ,ОтчетККМ.Номенклатура
| ,РеализацияРозница.Номенклатура
| ) Товар
| ,COALESCE(
| СписаниеТМЦ.Количество
| ,Реализация.Количество
| ,ОтчетККМ.Количество
| ,РеализацияРозница.Количество
| ) Колво
| ,COALESCE(
| СписаниеТМЦ.Коэффициент
| ,Реализация.Коэффициент
| ,ОтчетККМ.Коэффициент
| ,РеализацияРозница.Коэффициент
| ) Коэфф
| FROM (
| SELECT
| Ссылки.CHILDID Документ
|-- ,Журнал.IDDOCDEF Документ_вид
| FROM [__1S_crdoc] Ссылки
| INNER JOIN [Журнал] Журнал ON Ссылки.CHILDID = Журнал.IDDOC
| WHERE true
| AND Ссылки.PARENTVAL = :ДокОснование*
| AND Ссылки.MDID = '   0'
| AND Журнал.IDDOCDEF IN (:ВидДокумента.СписаниеТМЦ,:ВидДокумента.Реализация,:ВидДокумента.ОтчетККМ,:ВидДокумента.РеализацияРозница)
| AND Журнал.CLOSED=1
| AND Журнал.DATE <= :Дата2
| ) Документы
| LEFT JOIN [ДокументСтроки.СписаниеТМЦ] СписаниеТМЦ ON Документы.Документ = СписаниеТМЦ.IDDOC
| LEFT JOIN [ДокументСтроки.Реализация] Реализация ON Документы.Документ = Реализация.IDDOC
| LEFT JOIN [ДокументСтроки.ОтчетККМ] ОтчетККМ ON Документы.Документ = ОтчетККМ.IDDOC
| LEFT JOIN [ДокументСтроки.РеализацияРозница] РеализацияРозница ON Документы.Документ = РеализацияРозница.IDDOC
|) Товары
|GROUP BY Товар, Коэфф
|";
Запрос = глБазаДанных.НовыйЗапрос();
Запрос.Подставлять("Дата2" ,ДатаДок);
Запрос.Подставлять("ДокОснование" ,ДокОснование);
_ф = _GetPerformanceCounter();
Попытка
СписанныеКоличества = Запрос.ВыполнитьЗапрос(ТекстЗапроса);
Исключение
Возврат "Ошибка при отборе товаров.";
КонецПопытки;
глОтладка("1sqlite: " + (_GetPerformanceCounter() - _ф));
//}[*]___Arbuz, 28.06.2021 14:02:53


Валюта = ДокОснование.Валюта;
Курс = ДокОснование.Курс;
Кратность = ДокОснование.Кратность;


ТаблицаДокумента = СоздатьОбъект("ТаблицаЗначений");
ДокОснование.ВыгрузитьТабличнуюЧасть(ТаблицаДокумента);

// очищаем наш документ
УдалитьСтроки(); 

ТаблицаДокумента.ВыбратьСтроки();
Пока ТаблицаДокумента.ПолучитьСтроку() = 1 Цикл
Если (ТаблицаДокумента.КоличествоУчет > ТаблицаДокумента.Количество) Тогда
Товар = ТаблицаДокумента.Номенклатура;
Колво = ТаблицаДокумента.КоличествоУчет - ТаблицаДокумента.Количество;

// поищем в таблице уже списанных количеств
Поз = 0;
Пока (СписанныеКоличества.НайтиЗначение(Товар, Поз, "Товар") = 1)
   и (Колво > 0)
Цикл
СписанныеКоличества.ПолучитьСтрокуПоНомеру(Поз);
// пересчитаем количество в единицу измерения инвентаризации
СписКолво  = СписанныеКоличества.ВсегоКолво * СписанныеКоличества.Коэфф / ТаблицаДокумента.Коэффициент;
ПогашКолво = Мин(Колво, СписКолво);

Если ПогашКолво >= СписКолво Тогда
СписанныеКоличества.УдалитьСтроку(Поз);
Иначе
//{[*]Arbuz, 28.06.2021 13:56:32
// СписанныеКоличества.Колво = (СписКолво - ПогашКолво) * ТаблицаДокумента.Коэффициент / СписанныеКоличества.Коэфф;
СписанныеКоличества.ВсегоКолво = (СписКолво - ПогашКолво) * ТаблицаДокумента.Коэффициент / СписанныеКоличества.Коэфф;
//}[*]___Arbuz, 28.06.2021 13:56:32
КонецЕсли;

Колво = Колво - ПогашКолво;

Поз = 0;
КонецЦикла;

Если Колво > 0 Тогда
НоваяСтрока();
Номенклатура= Товар;
Количество = Колво;
Единица = ТаблицаДокумента.Единица;
Коэффициент = ТаблицаДокумента.Коэффициент;

// цену и сумму заполняем только по рознице
Если Склад.РозничныйСклад = 1 Тогда
Цена = ТаблицаДокумента.Цена;
Сумма = Цена * Количество;
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецЦикла; // по строкам основания       

Если КоличествоСтрок() = 0 Тогда
Возврат "В документе " + глПредставлениеДокумента(ДокОснование) +
" отсутствуют товары, учетное количество которых превышает фактическое";
КонецЕсли;

Возврат "";

КонецФункции // ЗаполнениеПоДокументуОснованию()
глБазаДанных это
глБазаДанных = СоздатьОбъект("SQLiteBase");
глБазаДанных.Открыть(":memory:");
глОтладка() можно заглушить или заменить на Сообщить()

И это не считая того, что, в принципе, с помощью прямых запросов на DBF можно получить на выборках из непосредственно полей документов/справочников(/проводок?) скорость сопоставимую (скорее превышающую) с выборками на чорных запросах из регистров. Конечно тут сильно зависит от архитектуры этих регистров, но признаюсь — грешен, пользуюсь во всю, часто лень проводить реорганизацию структуры базы.
Название: Re: МФ и SQL - как обойти кривую выдачу
Отправлено: Djelf от 30 мая 2025, 15:23
Поосторжнее с IN в 1sqlite, это коварная штука, если попадает в индекс, то может быть как и существенное ускорение, так и существенное замедление, вот пример того что может замедлить запрос
AND Журнал.IDDOCDEF IN (:ВидДокумента.СписаниеТМЦ,:ВидДокумента.Реализация,:ВидДокумента.ОтчетККМ,:ВидДокумента.РеализацияРозница)тут про 1sqlite не Орефкова (там движок старый был, он не понимал такую оптимизацию, а про мою сборку, на новых движках), движок будет последовательно делать несколько сканирований, по количеству их наличия в IN (старый движок не видел индексов в IN) и такого не умел
Отключается просто, добавьте "+" перед сравнением и сверьте результаты
AND +Журнал.IDDOCDEF IN (:ВидДокумента.СписаниеТМЦ,:ВидДокумента.Реализация,:ВидДокумента.ОтчетККМ,:ВидДокумента.РеализацияРозница)
Название: Re: МФ и SQL - как обойти кривую выдачу
Отправлено: Arbuz от 30 мая 2025, 15:35
Цитата: Djelf от 30 мая 2025, 15:23Поосторжнее с IN в 1sqlite, это коварная штука
Да-да, я помню. В данном случае я просто пренебрёг — там же неизменяемый список из четырёх значений (подумаешь, четыре сканирования по индексу  ;D ). И, помнится, я пробовал разные варианты именно с точки зрения производительности, этот меня полностью устроил. И в новых версиях вроде же существенно улучшили этот момент, в том числе на виртуальных таблицах?

ЗЫ: А, вспомнил! Там выборка катастрофически сужается сначала по PARENTVAL и MDID и этот IN практически не имеет значения.
Название: Re: МФ и SQL - как обойти кривую выдачу
Отправлено: Харлампий Дымба от 31 мая 2025, 01:05
Цитата: Arbuz от 30 мая 2025, 15:05Хм, ну вот, например, в ТиС в документе списание, ускорение в несколько тысяч раз, вместо десятков секунд — сотни миллисекунд:
Ну тут черный запрос изначально был как-то не на месте. Наверное и ВыбратьПодчиненныеДокументы() хоть и не миллисекунды бы занял, но за доли секунды бы отработал, что для ЗаполнениеПоДокументуОснованию() приемлимо.
Что, конечно, не отменяет великолепие прямого запроса.

А вот интересно - может есть у кого уже готовое или подскажете: быстрый способ получить список подчиненных документов с произвольным уровнем подчинения в SQL.
Как вариант: найти все Плат.пор/РКО выписанные на основе любого из документов в цепочке Счет-Реализация-СФ и Плат.пор/РКО. Т.е. задаем документ-основание (конкретный Счет) и виды нужных подчиненных документов (Плат.пор и РКО) + возможный отбор проведенные/удаленные - и получаем список подчиненных документов нужного вида. Ну и защиту от зацикливания:, т.е. исключать определенные виды документов - нужна заглушка, если попались документы с множественным подчинением, типа Выписка (где документы-основания могут быть в табличной части).
То что есть сейчас - это функция, использующая вызов ВыбратьПодчиненныеДокументы() в рекурсии. Для одного документа - ерунда, но для отчета в тысячу документов, это уже 2 минуты. Но не могу сообразить как построить запрос правильно.
Название: Re: МФ и SQL - как обойти кривую выдачу
Отправлено: Arbuz от 05 июня 2025, 16:04
Цитата: Харлампий Дымба от 31 мая 2025, 01:05может есть у кого уже готовое или подскажете: быстрый способ получить список подчиненных документов с произвольным уровнем подчинения в SQL.
Хотел было кинуть СтруктураПодч.ert Орефкова, но там для каждого узла графа выполняется отдельный запрос
запросРодителей = базаДанных.НовыйЗапрос();
запросРодителей.Подготовить("
|select
|substr(parentval, 3, 13) [Документ $Документ]
|from [__1S_crdoc] Ссылки
|where childid = @child and mdid = '   0'
|order by parentval
|");

запросПотомков = базаДанных.НовыйЗапрос();
запросПотомков.Подготовить("
|select
|Ссылки.childid [Документ $Документ],
|Журнал.iddocdef [Документ_вид]
|from [__1S_crdoc] Ссылки
|inner join [Журнал] Журнал on Ссылки.childid = Журнал.iddoc
|where Ссылки.parentval = @parent
|and Ссылки.mdid = '   0'
|order by Ссылки.childdate, Ссылки.childtime


ЗЫ: думаю, если помараковать, то можно и в один сделать через cte или подзапросами
Название: Re: МФ и SQL - как обойти кривую выдачу
Отправлено: Djelf от 05 июня 2025, 16:18
Цитата: Arbuz от 05 июня 2025, 16:04
Цитата: Харлампий Дымба от 31 мая 2025, 01:05может есть у кого уже готовое или подскажете: быстрый способ получить список подчиненных документов с произвольным уровнем подчинения в SQL.
Хотел было кинуть СтруктураПодч.ert Орефкова, но там для каждого узла графа выполняется отдельный запрос
запросРодителей = базаДанных.НовыйЗапрос();
запросРодителей.Подготовить("
|select
|substr(parentval, 3, 13) [Документ $Документ]
|from [__1S_crdoc] Ссылки
|where childid = @child and mdid = '   0'
|order by parentval
|");

запросПотомков = базаДанных.НовыйЗапрос();
запросПотомков.Подготовить("
|select
|Ссылки.childid [Документ $Документ],
|Журнал.iddocdef [Документ_вид]
|from [__1S_crdoc] Ссылки
|inner join [Журнал] Журнал on Ссылки.childid = Журнал.iddoc
|where Ссылки.parentval = @parent
|and Ссылки.mdid = '   0'
|order by Ссылки.childdate, Ссылки.childtime

Когда этот запрос создавался для 1sqlite, и создавался на той старой версии, не существовало рекурсивных запросов в движке sqlite.
Теперь они есть. Мне кажется что это можно в один запрос засунуть...
Скорее всего делать не буду, экономия в 2-3 мс это ерунда...
Название: Re: МФ и SQL - как обойти кривую выдачу
Отправлено: Харлампий Дымба от 05 июня 2025, 16:58
Огромное спасибо! Я знал, что всё уже придумано умными людьми.
Буду разбираться, когда руки. СтруктураПодч.ert тоже скачал, на всякий случай, тоже посмотрю
Название: Re: МФ и SQL - как обойти кривую выдачу
Отправлено: Arbuz от 05 июня 2025, 17:55
Цитата: Харлампий Дымба от 05 июня 2025, 16:58СтруктураПодч.ert тоже скачал, на всякий случай, тоже посмотрю
Тот запрос, что я выложил — он слегка подправлен под современную 1sqlite, в части подключения виртуальных таблиц