Как читать чужой код? Часть 3. Разбор и доработка запросов

05.06.23

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

Во всех вакансиях есть требование - умение читать чужой код. Но ни на одних курсах специально этому не учат. Чтобы устранить это противоречие, пишу данную статью. Рассмотрю случаи, в которых нам необходимо разбирать чужой код, поймём, чей код мы пытаемся разобрать, зачем и, главное, как. В статье описан личный опыт длиною в 18 лет начиная с версии платформы 7.7. Статья будет большой, набираемся терпения). Статья содержит в себе описание сценариев разбора кода, т.е. набор шагов. В статье не получится показать это на практике. Для этого планирую сделать онлайн или оффлайн курс, где на примерах будет показан разбор незнакомого кода. Статья разбита на 4 публикации для удобства изучения.

Сразу напишу вопросы, которые в статье не будут рассматриваться:

1. Разбор и отладка правил конвертации

2. Отладка фоновых заданий. 

3. Отладка асинхронных вызовов.

Здесь если начать описывать данный процесс, то получится статья о том, как они работают... А смысла писать давно описанное нет. Для меня пп. 2 и 3 это обычный код, который разбирается в других кейсах.

 

Кейс 5. Как разобрать и доработать запрос.

Здесь стоит написать, что каждый запрос решает какую-то задачу (сценарий). Иногда мы его знаем, но чаще всего ведём доработку чужого кода и чужих запросов лишь на догадках. Это плохо, конечно! Но сроки часто жмут, и разбираться со всей задачей некогда, иногда необходимо внести локальные изменения в запрос.

Сначала необходимо классифицировать задачи, которые требуют изменения запросов:

1. Запрос выдает не все данные, которые необходимы. Бывает, эта задача звучит так: Раньше работало нормально, а сейчас неверный результат заполнения чего-нибудь (документа, отчета, обработки).

2. Нужно добавить "несколько полей". 

3. Нужно, чтобы попадала и вот такая-то информация (в документ, движения, отчет, обработку).

4. Оптимизация работы запроса.

5. Нужно к существующему запросу добавить добавленный регистр(ы). 

Возможно, есть ещё какие-то сценарии доработки... Но главное - понять, какие шаги помогут разобраться в запросе!

1. Главное, что следует помнить, результат запроса - это таблица. Получилась эта таблица из других таблиц. Это означает, что при работе с запросами должна быть ассоциация работы с Excel. Ведь с Excel многие умеют работать! Например, условия запроса ни что иное как фильтр, который Вы наверняка с лёгкостью сможете накладывать в Excel.

2. Если таблицы большие (много колонок и много строк), представить себе результат запроса в голове очень сложно! Это должно мотивировать информацию либо записывать, либо распечатывать, либо сохранять в Excel и анализировать данные там. Конечно призыв печатать таблицы в 10 тыс и более записей можно поднять на смех... Это помогает, если запрос сложный, но его результатом является 100-200 записей. Такие данные вполне помещаются на 2х А4. Я использую сохранение данных в Excel и через наложение фильтров (включается Данные->Фильтры->Автофильтр) принимаю решение, какие данные из этой таблицы мне нужны, и какие отборы требуется наложить (или связи, если присоединяем к другой таблице). 

ВАЖНО: Не пытайтесь в голове представить, как выглядит результат запроса! Обязательно его выводите одним из предложенных ниже способов. Никогда Вы не сможете осознать, как отработали все связи, условия, как выглядят поля, которые получены через оператор ВЫБОР...КОГДА.

3. Выгрузить данные в таблицу можно следующими способами:

а. Если у Вас есть переменная с типом РезультаЗапроса, то нажмите Shift+F9 и напишите РезультатЗапроса.Выгрузить(). Результатом будет таблица значений.

б. Если у Вас есть переменная с типом ВыборкаИзРезультатаЗапроса, то написать нужно Выборка.Владелец().Выгрузить(). Функция Владелец() вернет РезультатЗапроса, Выгрузить() вернет таблицу значений.

Эти 2 способа помогут, если Вы работаете НЕ с временными таблицами, а с результирующим запросом.

Если необходимо посмотреть данные временной таблицы, можно воспользоваться одним из способов... Но здесь требуется обязательно использование объекта МенеджерВременныхТаблиц.

в. У менеджера временных таблиц есть свойство Таблицы. Когда Вы его просмотрите. то увидите что нумерация идёт с нуля. Чтоб посмотреть временную таблицу, нам требуется знать её номер! 

Далее необходимо нажать Shift+F9 и написать текст:

Запрос.МенеджерВременныхТаблиц.Таблицы[<НомерТаблицы>].ПолучитьДанные().Выгрузить(). 

На эту тему есть отдельные статьи, сильно расписывать не буду.

г. Написать простой запрос для получения таблицы из результата запроса:

Функция ПолучитьВТ(МенеджерВТ, ИмяВТ, Сортировка = "") Экспорт
	
    // Создаем новый запрос и назначаем переданный
    // менеджер временных таблиц. В тексте запроса
    // указываем получение всех данных из врем. таб.
    Запрос = Новый Запрос;
	
    Запрос.МенеджерВременныхТаблиц = МенеджерВТ;
	
    Запрос.Текст = "ВЫБРАТЬ
    | *
    |ИЗ
    | " + ИмяВТ + " КАК ВТ";
	
    // Результат запроса возвращаем в качестве таблицы
    // значений для удобного просмотра. В случае
    // возникновения ошибки возвращаем ее описание
    Если ЗначениеЗаполнено(Сортировка) Тогда
        Запрос.Текст = Запрос.Текст + "
        |
        |УПОРЯДОЧИТЬ ПО
        |" + Сортировка; 
    КонецЕсли; 
	
    Попытка
        Возврат Запрос.Выполнить().Выгрузить();
    Исключение
        Возврат "Ошибка получения временной таблицы: "
		
        + ОписаниеОшибки(); 
    КонецПопытки;
	
КонецФункции

Советую таблицу сохранить как печатную форму. Это можно сделать в отладчике через Shift+F9, у Вас должен быть тип ТаблицаЗначений. Потом F2 - показать значение. Когда откроется таблица справа вверху есть пиктограмма "Вывести список". Выбираем список нужных полей и жмём ОК. После закрытия формы просмотра результатов увидим заполненный данными запроса макет в конфигураторе.

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

В результате описанных действий мы получили некоторую визуализацию данных. Следующая задача - разобраться с условиями и связями, которые влияют на попадание записей в результирующий запрос. Наверняка возникает вопрос: и что я должен увидеть в регистрах? Ответ очень прост: какие измерение, ресурсы, реквизиты заполнены и, главное, какими значениями. Здесь важно выполнить некоторый анализ данных. Со временем некоторые поля регистра становятся не используемыми и не заполняются данными. Например, В ЗУПе есть интервальные регистры. Так вот "ПустойИнтервал" уже не используется, т.к. изменился принцип создания записей в этих регистрах и пустых интервалов не стало! Это можно увидеть только зайдя в регистр. Т.к. смотря на него в конфигураторе сразу возникает желание написать условие "НЕ ПустойИнтервал". На самом деле это условие ничем не поможет, т.к. поле больше не используется!

Как известно, условия накладываются в следующей последовательности:

-- Сначала в параметрах виртуальных таблиц (если они используются в запросе)

-- Далее в связях между таблицами. Связи определяют, какие данные будут присоединены к основной таблице запроса.

-- В последнюю очередь работают условия в блоке после слова "ГДЕ". ВАЖНО: Эти условия накладываются уже на результат запроса, т.е. после объединения таблиц

5. Прежде чем разобраться с условиями и связями, опишу способ сравнения результата запроса до изменения с результатом после изменения. Любую таблицу в 1С как в пользовательском режиме, так и в конфигураторе можно сохранить, например, в *.mxl. Как получить таблицу чуть выше описал.

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

Далее вносим какие-то изменения в запрос, запускаем отладчик, и получаем таблицу уже после Ваших изменений. Полученную таблицу также сохраняем в *.mxl.

Далее в 1С есть специальный пункт меню Файл->Сравнить файлы. В первый выбираем до изменений, во второй после, поле "Как" заполняем значением "Табличный документ". Жмём ОК и увидим разницу. Советую проверять эту разницу как можно детальней, т.е. как можно больше строк проанализировать и понять правильность их изменения. Часто бывает так, что неверная запись в запросе имеет 4-х значный порядковый номер! Если записей очень много (более 10 тыс.) советую пролистать на середину, там проверить пару тысяч записей, потом в конец и с конца проверить пару тысяч записей. Это позволит найти все ошибки в результате выполнения доработанного запроса.

6. Обратим внимание на главную таблицу запроса. В блоке соединений она слева и в тексте запроса и в конструкторе запросов. Если данные выбираются не из физической таблицы и не из временной, а из виртуальной таблицы, на это нужно обратить особое внимание. Виртуальные таблицы нигде не хранятся. Как известно, они формируются платформой в момент исполнения запроса. Состав записей в этой таблице зависит от параметров виртуальной таблицы. Чтоб разобраться какие данные она выдаёт нужно сделать 3 действия:

а. Написать (скопировать) отдельный запрос с теми же параметрами без соединений с другими таблицами и без блока условий "ГДЕ". Результат запроса просматриваем и анализируем как описано выше. Это позволит понять, как выглядит главная таблица запроса без всяких дополнений.

б. Стереть в скопированном запросе параметры виртуальных таблиц. Стереть нужно все кроме периода. Так Вы увидите какие записи отфильтрованы параметрами виртуальных таблиц. 

в. Почитать в статье об используемой виртуальной таблице! Сделать это надо сразу! Несмотря на то, что я написал последним пунктом. Ибо если Вы не знаете назначение таблицы, только чудо может Вам помочь написать или исправить написанный запрос!

7. Теперь тем же способом изучим влияние условий в секции "ГДЕ" на результат запроса. Иногда условия настолько сложны и их так много, что даже опытным разработчикам не очевидно, какое из условий удаляет из результата нужную запись. В такой ситуации делаем следующие действия:

а. Комментируем все условия и смотрим на "грязный" результат запроса. Убеждаемся, что в нём есть нужные записи. 

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

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

8. Осталось проанализировать соединения. Самое простое соединение - ЛЕВОЕ. Причина в том, что левое соединение не уменьшает количество записей. НО! Если в связях задать недостаточное количество условий, то количество записей может увеличиться. Поиск дублей это одна из задач, с которой сталкиваются разработчики. Самый простой способ дописать "РАЗЛИЧНЫЕ" после слова "ВЫБРАТЬ". Но способ костыльный и не всегда спасает! Поэтому надо разбираться в соединениях! Вот какие действия нужно предпринять:

а. Не просто так исходно упомянул ЛЕВОЕ СОЕДИНЕНИЕ. Это соединение означает, что к основной таблице присоединяются все записи правой таблицы, которые удовлетворяют условиям связи. Как уже упомянул ранее, одной записи левой таблицы могут соответствовать несколько записей правой таблицы. Количество записей результирующей таблицы будет увеличено на количество дублей. В большинстве случаев, дубли являются ошибкой. Дубли будут, т.к. мы из правой таблицы берём не все поля, а лишь несколько. 

б. При возникновении дублей необходимо проанализировать отдельно правую таблицу. Нужно попробовать найти ещё одно поле для связи, чтоб устранить дубли. 

в. Если это не получается, советую воспользоваться группировкой результата запроса. Она уберёт лишние записи. По влиянию на результат запроса конструкция "ВЫБРАТЬ РАЗЛИЧНЫЕ" и "СГРУППИРОВАТЬ ПО" совпадают, если группировку сделать по всем полям запроса. НО! Группировка позволяет к некоторым полям применять агрегатные функции. Это может быть полезно с точки зрения результата и показывает, что запрос был осознанно написан автором. Выбор различных чаще показывает нежелание разбираться в запросе и костыльный вариант решения задачи.

г. Как разобраться с другими видами соединений? Разберём ВНУТРЕННЕЕ СОЕДИНЕНИЕ. Это соединение предназначено для фильтрации данных. Многие не профи разработчики его используют повсеместно вместо условий в конструкции "ГДЕ". Такое использование часто на практике приводит к потере нужных записей. Связано это с тем, что мы не можем спрогнозировать мысленно как отработает соединение на всех записях запроса. Возникает эта проблема при больших размерах таблиц. Как минимум для проверки таких запросов рекомендую использовать ЛЕВОЕ СОЕДИНЕНИЕ, а лишние записи фильтровать условием НЕ ЕСТЬ NULL. Причём сначала нужно увидеть результат соединения, проверить много записей (как описано выше), а потом уже накладывать условие. Часто именно в результате такой проверки и придумываются условия, которые нужно наложить. 

ВАЖНО: Если условия накладывать в связях и использовать ВНУТРЕННЕЕ СОЕДИНЕНИЕ, Вы не увидите, какие записи исключаются из результата запроса. Использование этого соединения оправдано для небольших таблиц, когда точно известно какие записи есть в каждой из таблиц и какие записи будут исключены. Если принято решение использовать этот вид соединения, необходимо проверять его через ЛЕВОЕ СОЕДИНЕНИЕ с условием НЕ ЕСТЬ NULL.

Замена внутреннего соединения на левое помимо проверки обычно позволяет и разобраться в таком запросе. Начинают отображаться скрываемые записи и через сравнение таблиц можно увидеть что поменялось.

9. Осталось разобраться с конструкциями ПОЛНОЕ СОЕДИНЕНИЕ и ОБЪЕДИНИТЬ ВСЕ. Рассмотрю эти конструкции вместе, т.к. обе конструкции приводят к появлению лишних записей и нужно крайне аккуратно ими пользоваться. Более того, конструкция ПОЛНОЕ СОЕДИНЕНИЕ помимо того что они лишние, создаёт их с полями со значением NULL. Рассмотрим действия, которые с одной стороны помогут разобраться в запросе, а с другой не наделать ошибок при использовании этих конструкций. Вот что важно знать:

а. Конструкцию ПОЛНОЕ СОЕДИНЕНИЕ использовать как можно реже, когда нет возможности решить задачу по-другому.

б. Не путать эти конструкции между собой! Соединение предназначено для схлопывания совпадающих по условиям связей записей и добавления записей из обеих таблиц, которые не соответствуют условиям связи. При использовании соединения нам неважно, сколько полей в соединяемых таблицах! Мы берем только необходимые нам поля и всё. Например, есть 2 таблицы по 200 записей. 150 записей по условиям связи совпали. Это значит, что в результате запроса будет 250 записей. 

в. Вторая конструкция предназначена для объединения таблиц с однотипной информацией. Более того, количество и тип значения полей в объединяемых запросах должны совпадать. Количество должно совпадать обязательно, а тип значения желательно! Здесь нет никаких условий уже. Если взять те же таблицы по 200 записей, то итоговое количество записей будет 400. Если в конструкторе запроса в одном из запросов не указать значение поля, автоматически подставится значение NULL. Следовательно, если видите в тексте объединяемого запроса NULL необходимо задуматься, вдруг это ошибка и данное поле можно заменить на нормальное значение. Если в первом запросе поле примитивного типа, значит необходимо заменить на пустое значение примитивного типа. (Ложь, 0, "", Дата(1,1,1,0,0,0)). Если далее поля будут суммироваться, то хотя бы ошибки не будет. 

г. Если использовать конструкцию "ОБЪЕДИНИТЬ" без слова "ВСЕ", то в запрос не будут добавлены дублирующие записи. Дубли в данном случае проверяются по всем полям. Как понять, какой вариант использовать? Если у Вас есть 2 таблицы из разных источников с ценами номенклатуры, то дубли с одинаковой ценой никому не нужны! Если у Вас есть 2 таблицы с остатками по номенклатуре, то одинаковые остатки мы в итоге должны просуммировать, убирать дублирующие записи нельзя. Призываю использовать эту конструкцию осознанно в зависимости от решаемой задачи. Всегда нужно помнить о дублирующихся записях и понимать, будут ли они мешать. При доработке запросов необходимо разобраться в этом вопросе. Ответ на этот вопрос поможет выявить сценарии работы. Сам стараюсь слово "ВСЕ" использовать как можно реже, во избежание лишних записей и ошибок! 

д. Если в запросе с "ОБЪЕДИНИТЬ ВСЕ" много объединяемых запросов, то понять, из какого запроса запись, очень сложно! Это является проблемой, когда в получившейся таблице есть неверные или лишние записи. Чтоб это исправить, необходимо понять, какой из объединяемых запросов выдал эту запись. Для этого необходимо добавить во все запросы первым поле "НомерЗапроса". Т.е. добавить строку "1 КАК НомерЗапроса,". В результирующем запросе можно будет понять, какие записи из какого запроса попали. Далее уже можно будет разобрать отдельный запрос, как это описано выше. Смотрим на условия, соединения, изучаем исходные таблицы и т.д. 

е. Как уже писал, при использовании "ПОЛНОЕ СОЕДИНЕНИЕ" могут появиться в некоторых полях значения NULL. Это значение появится в двух случаях:

-- Если в правой таблице по условиям связи не находится записи, то все поля, получаемые из правой таблицы будут иметь значение NULL. Необходимо воспользоваться функцией ЕСТЬNULL и продумать, чем заменить значение NULL.

-- Если запись попадает из правой таблицы, то все поля, которые берутся из левой таблицы, будут иметь значение NULL. 

ВАЖНО:

Из этого следует, что ВСЕ поля запроса при использовании "ПОЛНОЕ СОЕДИНЕНИЕ" должны быть обработаны с помощью функции ЕСТЬNULL. При разборе чужих запросов часто сталкиваюсь с ошибками из-за того, что эту функцию не используют. 

Та же проблема есть при использовании "ЛЕВОЕ СОЕДИНЕНИЕ". Все поля из правой таблицы должны быть обработаны функцией ЕСТЬNULL.

Т.к. при использовании "ВНУТРЕННЕЕ СОЕДИНЕНИЕ" попадают только записи, которые есть в обеих таблицах, значение NULL появиться в запросе не может! Значит использовать функцию ЕСТЬNULL на всякий случай не нужно! Это уже будет выглядеть как непонимание работы соединений. 

Некоторые приёмы, для облегчения разбора запросов:

1. Запрос необходимо разбирать "с конца". Не нужно пытаться понять весь запрос, особенно если он огромен и текст запроса собирается динамически в 15 модулях! Ваша задача - найти место требующее доработки. Для этого с конца просматриваем таблицы запроса, анализируем их описанными выше способами. Как только определили нужное место - остальные таблицы не смотрим даже ради интереса! Не нужно терять зря время.

2. Посмотрите, где используется результат запроса? Его используют обычно так:

-- Для заполнения таблиц/табличных частей

-- Для формирования движений

-- Для проверки правильности каких-то данных

-- Запросы для заполнения отчетов и регламентированной отчетности.

Когда понимаешь, куда ложатся данные запроса, становится немного легче в этом разбираться.

3. Проверяйте в отладчике каждую временную таблицу или каждый написанный запрос. Это позволит вовремя заметить ошибку, устранить её сразу и далее написать верные запросы. Если пропустить ошибку и обнаружить её через пару недель, то будете заново разбираться в своём же запросе

4. Если текст запроса собирается в разных процедурах, найдите место, где он уже собран полностью, и через Shift+F9 посмотрите полный текст запроса. Рекомендую его скопировать и закинуть в конструктор запросов. Далее последовательно открывайте отладчиком временные таблицы и анализируйте запрос, который их получает. 

5. Найти место, где формируется текст нужного Вам запроса, можно через поиск по всем текстам. В строку поиска нужно написать либо название временной таблицы, либо одно из условий запроса или связи, которое Вам кажется уникальным. 

Осталось рассмотреть особенности разбора запроса для его оптимизации.

1. Конечно, самым идеальным вариантом будет анализ плана запроса! НО! Этим механизмом далеко не все владеют! Поэтому рассматривать его не будем в данной статье, это уже много раз описано в других статьях. Расскажу о вполне очевидных моментах, для которых не требуется быть экспертом по технологическим вопросам.

2. Одним из очевидных моментов является использование вложенных запросов. На эту тему есть и стандарт разработки, много статей написано почему это лучше не делать. Коротко - выбирается неоптимальный план выполнения запроса. Сам стараюсь это не использовать совсем. Если кто-то использует то вот несколько советов:

-- Старайтесь во вложенном запросе не обращаться к физическим либо виртуальным таблицам, т.е. к базе данных. Желательно обращаться к временным таблицам

-- Если есть потребность обратиться во вложенном запросе к физической таблице - желательно, чтоб эта таблица была маленькой, до 1000 записей. Например, справочник Организации, Подразделения, Склады и т.д. 

-- При обращении ко временным таблицам, также желательно, чтоб размер временной таблицы во вложенном запросе был минимален. Не нужно регистр ЦеныНоменклатуры помещать во временную таблицу и обращаться к ней во вложенном запросе. Скорей всего план выполнения запроса будет не оптимален.

3. При использовании виртуальных таблиц остаточного регистра накопления не нужно без надобности использовать таблицу ОстаткиИОбороты. Её формирование занимает некоторое время, даже если использованы отборы в параметрах виртуальных таблиц.

4. Есть простые правила при наложении условий и связей:

-- Не использовать конструкцию ИЛИ в условиях и связях если используются физические или виртуальные таблицы. Конструкция ИЛИ отключает использование индексов.

-- Условия и связи должны накладываться по индексированным полям. Вам необходимо контролировать, чтоб условия использовали индексы по порядку. Т.е. если у регистра 3 измерения, а в условии/связи использовать только первое и третье, то всё равно произойдёт полное сканирование таблицы. Необходимо такой запрос разбить на 2. На эту тему есть отдельный стандарт разработки, прошу ознакомиться.

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

5. Старайтесь не использовать разыменовывание полей. Если необходимо вытащить поля справочника Организации, то можно не делать ЛЕВОЕ СОЕДИНЕНИЕ, т.к. присоединяемая таблица маленькая. Вряд ли возникнут сложности с таким запросом. Но если необходимо вытащить поля справочников Номенклатура, Сотрудники и т.п. обязательно добавлять таблицу справочника в запрос и связывать по Ссылке левым соединением.

6. Отдельно напишу, что разыменовывание полей составного типа может привести к сильному замедлению работы, в каких-то случаях даже к серьёзным тормозам всего сервера! Делать так ЗАПРЕЩЕНО! Необходимо присоединять нужную таблицу левым соединением. 

7. При использовании виртуальных таблиц регистра накопления не рекомендуется просто так указывать периодичность Регистратор и Запись. Это должно быть обосновано условием решаемой задачи. Расчет итогов происходит по бОльшему количеству записей, что не добавляет скорости.

Наверное есть ещё какие-то ситуации, в которых нужно оптимизировать запросы... Описал самые критичные случаи. Есть главное правило: соблюдайте стандарты разработки 1С и проблем в коде у Вас не будет. Для запросов это правило работает где-то в 90% случаев. Но на больших объёмах данных бывают ситуации когда лучше нарушить стандарт, чтоб запрос работал быстрее. Этот кейс рассматривать не стану, т.к. нарушать правила надо осознанно и очень аккуратно!

Уверен, что проделав действия, описанные в этом кейсе, запрос будет успешно разобран на составляющие, оптимизирован и доработан, как Вам необходимо в соответствии с заданием. 

Остальные части доступны по ссылкам:

Часть 1. Общие вопросы. Доработка чужого кода. Code review.

Часть 2. Доработка типовой конфигурации. Обновление доработанной типовой конфигурации.

Часть 4. Программный интерфейс. Исправление чужих доработок.

Добавляйте себе в избранное,  ставьте "+". Статья разрабатывалась 1,5 месяца, а опыт копился 18 лет!

 

Также напомню о своих предыдущих публикациях, в особенности про статью об архитекторе. Текст статьи полностью переработан, сглажены углы. Будет интересно, даже если уже читали. Вот ссылки:

1. Кто такой архитектор. Редакция 2!

2. Пример работы с файлами odt в клиент-серверной модели работы

3. Использование ПоказатьВопрос() в событии НачалоВыбора()

Чужой код чтение кода доработать чужой исправить оптимизация проверка помощь разработка запрос программный интерфейс

См. также

SALE! %

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

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

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

12000 10000 руб.

02.09.2020    92978    474    379    

530

Нахождение уникальных наборов строк таблицы запросом

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

Решение задачи нахождения уникальных наборов строк таблицы запросом

23.07.2023    4307    tormozit    78    

38

Структура запроса

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

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

1 стартмани

21.06.2023    4230    49    obmailok    35    

51

MS SQL Server: изучаем планы запросов

Запросы HighLoad оптимизация Запросы Бесплатно (free)

Многие знают, что для ускорения работы запроса нужно «изучить план». При этом сам план обычно обескураживает: куча разноцветных иконок и стрелочек; ничего не понятно, но очень интересно! Аналитик производительности Александр Денисов на конференции Infostart Event 2021 Moscow Premiere рассказал, как выполняется план запроса и что нужно сделать, чтобы с его помощью находить проблемы производительности.

20.06.2023    7398    Филин    37    

92

Шаблоны для применения cтандартов и методик разработки конфигураций 1С

Рефакторинг и качество кода Платформа 1С v8.3 Абонемент ($m)

Готовые шаблоны текста для применения cтандартов и методик разработки конфигураций 1С, инструментарий. Версия платформы 8.3.22.1851.

2 стартмани

04.06.2023    7227    46    improg    34    

39

Ревьювер. Инструмент для проведения code review

Рефакторинг и качество кода Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

Если вы работаете в команде разработчиков, то, вероятно, знакомы с процессом код-ревью. Это необходимый шаг в разработке программного обеспечения, который помогает выявить ошибки и улучшить качество кода. Однако, процесс ревью может занимать много времени и быть довольно утомительным, особенно на ранних этапах разработки. Мы столкнулись с этими проблемами в команде и решили упростить процесс код-ревью с помощью внутреннего инструмента. Он значительно облегчил процесс ревью на определенном этапе работы и сократил время на рутинную работу. В результате, мы смогли значительно упростить процесс код-ревью в команде, что сэкономило время и улучшило качество кода.

16.05.2023    3551    leobrn    12    

50

Применение cтандартов и методик разработки конфигураций на практике

Рефакторинг и качество кода Платформа 1С v8.3 Бесплатно (free)

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

15.05.2023    6257    improg    56    

67

Все консоли запросов для 1С

Запросы Бесплатно (free)

Список всех популярных обработок.

17.03.2023    18816    kuzyara    70    

147
Комментарии
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
1. hiduk 120 20.09.21 15:40 Сейчас в теме
Не увидел про консоль запросов - на мой взгляд очень удобный механизм.
2. biimmap 1381 20.09.21 15:49 Сейчас в теме
(1) Не готов разделить Ваш взгляд. В своей практике им не пользуюсь, потому и не описал. Всё таки статья про мой личный опыт. Есть много способов других посмотреть результат.

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

С другой стороны и не возражаю против того, когда его используют. Дело вкуса и привычек. Главное, чтоб смотрели на результат запроса до и после изменений. А как это будут делать не столь важно. Я предложил свои способы.
3. ritchie 20.09.21 17:43 Сейчас в теме
(2)
>Если нужны временные таблицы, которые формируются где-то вне процедуры/функции, консоль не >подходит
Что это значит?НЕ использовать консоль?
Самое простое добавть в запрос
; выбрать * из НужнаяВременнаяТаблица
4. biimmap 1381 20.09.21 18:46 Сейчас в теме
(3) Что использовать, а что нет - каждый решает сам. Ещё раз повторюсь, что я не использую. Но никому не навязываю свой подход.

Откуда ж выбирать планируете, если временные таблицы программным интерфейсом получаются?
5. gybson 20.09.21 19:43 Сейчас в теме
(4) В отладчике можно посмотреть и скопировать текст запроса. Временные таблицы добавить в пакет тоже не огромная проблема.
siamagic; +1 Ответить
6. biimmap 1381 20.09.21 19:47 Сейчас в теме
(5) Не спорю. А задайте себе вопрос: ЗАЧЕМ? Если там же в отладчике можно и продолжить разбор запроса! Появляется лишнее звено в работе, для обслуживания которого нужно потратить время.

И вот далеко не всегда закинуть таблицы в пакет можно легко! Не отговариваю... Просто обдумайте выхлоп от Ваших действий.
8. gybson 20.09.21 20:36 Сейчас в теме
(6) чтобы не копировать таблицы в эксель, например. В консоли сразу будет видно, что какая-то из временных таблиц пустая и соединение с ней дает пустой результат, например. И в принципе при разработке запроса удобнее его разрабатывать на живых данных, а не абстрактно.
siamagic; +1 Ответить
9. biimmap 1381 20.09.21 20:42 Сейчас в теме
(8) Если почитать внимательно, то в Эксель таблицы предлагаю выводить для их анализа. И анализ не на пустоту таблицы. Вторая причина вывода - сравнить до и после. Я понял, что Вы фанат консоли. Уверен не одинокий фанат)))

Как раз в отладчике я и смотрю всё без консоли, чтоб на реальных данных. Я не пишу отчеты, мне не для этого нужно запросы смотреть. Обычно меняю сложную логику расчетов в документах, либо пишу сложные обработки. В тексте упоминал, что разработку веду только в отладчике и только на реальных данных. никакие тестовые примеры не признаю.
23. SirStefan 52 23.09.21 17:29 Сейчас в теме
(6), в Инструментарии Разработчика одной строчкой в табло запрос со всеми таблицами переносится из отладчика в консоль запросов. Зачем? Чтобы иметь возможность изменять запрос и смотреть что получится. Это гораздо удобнее, стоит попробовать.
24. biimmap 1381 23.09.21 17:36 Сейчас в теме
(23) Вы невнимательно читали, когда я писал, что временные таблицы динамически формируются в разных функциях в разных модулях... Чем мне поможет консоль здесь?

!!!Для всех фанатов консоли напишу!!!: когда был ЗУП 2.5 и УПП, я тоже ей пользовался в древние времена. Но там запрос располагался в одной процедуре, его не надо было собирать по 10 модулям. Потом, когда коллеги подсказали, что можно написать процедуру ПолучитьВТ, больше ни разу не пользовался без потери для скорости и качества разработки!
20. RustIG 1728 22.09.21 10:01 Сейчас в теме
(5) автор статьи, Павел, забыл написать, что в основном он работает с ЗУПовскими запросами - портянками запросов, которые складываются программно... Его метод имеет право на жизнь....
26. gybson 27.09.21 20:09 Сейчас в теме
(20)проведение документов в ERP и УТ такая-же портянка. Но собрать то ее надо один раз всего. Конечно печально, когда по ходу дела туда таблицы значений могут подкладывать, но это не так сложно переделать на временную таблицу. Зато сразу можем работать с условиями и отборами и все на живых данных. Да и создание нового запроса изначально удобнее вести в консоли, а это не такая и редкая задача =)

Особенно радует, что текст под замену в запросах оформляют параметром и часто можно его так и оставить "неопределено".
19. RustIG 1728 22.09.21 09:58 Сейчас в теме
(1) вы какой консолью пользуетесь? и с какими конфигурациями работаете? и с какими блоками учета?
21. biimmap 1381 22.09.21 10:16 Сейчас в теме
(19) Ты вроде написал, что моя специфика - ЗУП. Я правда не вижу плюсов в консоли))) Поэтому просто в отладчике всё разбираю. Вставляю в свой код ПолучитьВТ() и довольно быстро всё анализирую.
22. RustIG 1728 22.09.21 10:30 Сейчас в теме
(21) Павел, ты явно ошибся. Я не тебе вопрос задал про консоль.
25. hiduk 120 24.09.21 10:14 Сейчас в теме
(19) Обработка "Запросник", Автор доработок: Тезин Владимир. Бухгалтерия предприятия 3, УПП. С ЗУП-ом признаюсь, дело не имею.
7. gybson 20.09.21 20:18 Сейчас в теме
Типовой код в УТ =))

"|	АналитикаУчетаНоменклатуры.Номенклатура.ЕдиницаИзмерения.Представление КАК ЕдиницаИзмеренияНаименование,"


Да, формирование печатной формы, не очень серьезная нагрузка.

Но и далее видим

"|	Остатки.АналитикаУчетаНоменклатуры.Номенклатура.ЕдиницаИзмерения КАК ЕдиницаИзмерения," в процедуре ЗапросРаспределенияРезервовПоТаблицеОстатков


И там полно такого кругом и даже в расчете НДС и везде вообще.

И для примера берем запросы

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

и

ВЫБРАТЬ
	КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Номенклатура2.ЕдиницаИзмерения) КАК АналитикаУчетаНоменклатурыНоменклатураЕдиницаИзмерения
ИЗ
	РегистрНакопления.ВыручкаИСебестоимостьПродаж.Обороты КАК ВыручкаИСебестоимостьПродажОбороты
		ЛЕВОЕ СОЕДИНЕНИЕ Справочник.КлючиАналитикиУчетаНоменклатуры КАК КлючиАналитикиУчетаНоменклатуры
			ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК Номенклатура2
			ПО КлючиАналитикиУчетаНоменклатуры.Номенклатура = Номенклатура2.Ссылка
		ПО (ВыручкаИСебестоимостьПродажОбороты.АналитикаУчетаНоменклатуры = КлючиАналитикиУчетаНоменклатуры.Ссылка)
Показать


Разницы в скорости почти никакой и первый в среднем быстрее даже. В выборке 29к записей

Отчет "Выручка и себестоимость продаж"

"КОГДА ЕСТЬNULL(РасчетСебестоимости.Ссылка.ПредварительныйРасчет, ЛОЖЬ)"
- а ведь ссылка тут это то самое поле составного типа.

Итого, с точкой в целом можно не заморачиваться и никто уже этого и не делает в типовых.
10. biimmap 1381 20.09.21 20:46 Сейчас в теме
(7) Т.к. сам работал в 1С... Знаю что код тестируется на предмет временных затрат. Возможно коллеги сумел как-то сделать оптимальным то, что считают грубой ошибкой. Это можете на конференции спросить, Вам ответят сами разработчики.

Так писать можно, если разыменовывается небольшая таблица. Конечно, справочник Номенклатура таковой не назовёшь... Но всё же не стану пропагандировать такой способ. Ну и кстати место это в отчете! К отчетам обычно меньше требований предъявляется. Попробуйте найти подобное в алгоритмах проведения или расчета себестоимости... Вряд ли.
11. gybson 20.09.21 21:42 Сейчас в теме
(10) Не боги горшки обжигают =) Берем "Управление холдингом", в нем регистр "ЛимитыПоБюджетам". Это оборотный регистр. Как коллеги из 1С получают из него остатки в отчете по лимитам? Ну правильно, берут временную таблицу без указания периода и складывают-вычитают нужные обороты. И тут заказчик просит добавить столбец с лимитом на определенную дату.

Да просто там же посмотреть Функция ВыполнитьКонтрольЛимитов(Запрос) в модуле КонтрольУХБюджетныеЛимиты. Запрос прям ух
12. biimmap 1381 20.09.21 21:49 Сейчас в теме
(11) УХ и ЕРП (КА, УТ) пишут разные отделы) В каждом отделе свои подходы
13. gybson 21.09.21 08:57 Сейчас в теме
(12)У Вас рекомендации для какого отдела? :)

Тогда уж стоит отдельно упомянуть и о виртуальных таблицах регистров бухгалтерии, где неумелый запрос может не выполниться вообще никогда.
rybolovlev_ms; +1 Ответить
14. biimmap 1381 21.09.21 09:46 Сейчас в теме
(13) Для всех вроде бы))) Старался писать без привязке к конфигурации. Только в разборе программного интерфейса писал про ЗУП, но в остальных конфигурациях тот же подход.
15. bulpi 211 21.09.21 12:42 Сейчас в теме
" Но если необходимо вытащить поля справочников Номенклатура, Сотрудники и т.п. обязательно добавлять таблицу справочника в запрос и связывать по Ссылке левым соединением."

ИМХО, sql сам добавит таблицу, и результирующий план запроса будет одинаковым. А текст запроса проще и компактнее.
anbupro; sashocq; +2 Ответить
16. alex_sayan 21.09.21 18:19 Сейчас в теме
вакансиях есть требование - умение читать чужой код


По-моему самое нелепое из всех требований. Нужно уметь писать простой и понятный код. Нужно наводить порядок, а не искать тех, кто сможет жить в беспорядке
17. biimmap 1381 21.09.21 19:13 Сейчас в теме
(16) Что ж в нём нелепого? У всех разное время уходит на разбор кода. А есть начинающие спецы, которые сложные моменты в принципе не могут разобрать. Так что требование норм, наряду с умением писать нормальный код.
18. alex_sayan 22.09.21 08:08 Сейчас в теме
(17) это требование звучит как "умение находить вещи в заваленном шкафу". Первостепенным должно быть наведение порядка, а не умение приспосабливаться к беспорядку
27. Cyberhawk 134 04.02.22 18:35 Сейчас в теме
Выбор различных чаще показывает нежелание разбираться в запросе и костыльный вариант решения задачи

Если использовать конструкцию "ОБЪЕДИНИТЬ" без слова "ВСЕ", то в запрос не будут добавлены дублирующие записи ... Сам стараюсь слово "ВСЕ" использовать как можно реже, во избежание лишних записей и ошибок!
В этих двух утверждениях я вижу противоречие...
28. biimmap 1381 04.02.22 19:00 Сейчас в теме
(27) Коли не секрет, какое? Конструкции используются для абсолютно разных целей! Где там может быть противоречие даже интересно...

ОБЪЕДИНИТЬ - мы соединяем таблицу из разных источников, чтоб не дублировать строки, что невероятно часто бывает в такой ситуации - убираем слово ВСЕ. Здесь лишние записи получаются из-за сворачивания измерений, т.е. некоторые не используем в запросе, либо несколько примерно одинаковых регистров. Бывает даже из одного регистра выбираешь список сотрудников по разным условиям, и один и тот же сотрудник по двум условиям попадает. Зачем мне дубль? Это осознанное действие!

РАЗЛИЧНЫЕ можно встретить абсолютно в любом запросе с соединениями! И вот это уже проблема!
29. Cyberhawk 134 04.02.22 19:38 Сейчас в теме
(28)
Зачем мне дубль? Это осознанное действие!
У читателя такого запроса не будет информации о намерениях писателя этого запроса, поэтому осознанным можно называть лишь такой текст, в котором результат объединения (со словом "ВСЕ") помещается во временную таблицу, которая в следующем запросе пакета уже явным образом сворачивается через СГРУППИРОВАТЬ ПО.
Отсутствие же слова "ВСЕ" - точно так же как и присутствие РАЗЛИЧНЫЕ - может показывать нежелание писателя разбираться в запросе.
30. biimmap 1381 04.02.22 21:42 Сейчас в теме
(29) раньше я также думал. А теперь использую принцип такой: на каждом этапе запроса, т.е. в каждой следующей таблице не должно быть лишних записей!

Здесь важно понять, что добавление ключевого слова ВСЕ плодит лишние записи. И если нет цели их увидеть и проанализировать, либо сосчитать количество дублей, то ВСЕ добавлять в запрос не нужно. Вот уже год примерно как не пользуюсь этой конструкцией! Просто нас всех приучили к тому, что пишется ОБЪЕДИНИТЬ ВСЕ. Во всех курсах и книгах так написано. А анализировать последствия в этих пособиях никто не учит! А стоило бы!

Так что мнение Ваше довольно распространённое, но приводит к лишним записям и действиям по избавлению от них. Я делаю по-другому.

Ещё раз напишу, что конструкция РАЗЛИЧНЫЕ имеет другое назначение и убирает записи, которые появились в результате неверных соединений. Либо в описанном в статье верном случае, когда используешь не все измерения.
31. Vinzor 54 18.04.22 11:00 Сейчас в теме
Уважаемый автор.
А где можно увидеть это, если Вы это выкладывали?

1. Разбор и отладка правил конвертации
2. Отладка фоновых заданий.
3. Отладка асинхронных вызовов.
32. biimmap 1381 18.04.22 11:08 Сейчас в теме
(31) Добрый день. В первой статье специально написал, что указанные Вами пункты не рассматриваются в статьях.
33. vipetrov2 23.12.22 06:52 Сейчас в теме
Самый надежный способ разобраться, это сделать инструментарий по сохранению в файл данных, конкретно здесь это текст запроса и данные таблицы. Сейчас просто голый запрос мало где встретишь, используются СтрЗаменить(), могут рекурсией формироваться или в логической машине, это когда формируется свой список команд, а потом на основании их будут получаться данные, еще и в несколько этапов через разные запросы. А так ты можешь получить сразу все срезы данных на разных этапах.
34. chess762 05.06.23 11:51 Сейчас в теме
В варианте Г. выгрузка данных из временной таблицы у меня проверка модуля ругается на неопределенную переменную
Сортировка
, как она должна быть определена?
35. biimmap 1381 05.06.23 12:24 Сейчас в теме
(34) Это должна быть функция. Сортировка - параметр. Поменял код в публикации.

Странно, что никто на это не обращал ранее внимания)
chess762; +1 Ответить
36. chess762 29.06.23 16:16 Сейчас в теме
Выборка.Владелец().Выгрузить().
А как посмотреть результат выборки перечня номенклатуры таблицы значений, который находиться в таблице значений функции Выгрузить()?
Прикрепленные файлы:
37. biimmap 1381 29.06.23 16:26 Сейчас в теме
(36) Нажимаете F2, раскрываете плюсиком слева строку таблицы и ещё раз F2 на поле ПереченьНоменклатуры.
chess762; +1 Ответить
38. user1950534 08.08.23 09:09 Сейчас в теме
Прекрасно работают вложенные запросы, если их грамотно составить. В сотни раз быстрее, чем создание временных таблиц (да еще и с индексацией). При отборе по первому и третьему измерению регистра, во-первых, он не будет сканировать всю таблицу, а отберет данные по первому измерению и эти данные будет сканировать. Во-вторых, скорее всего придется проиндексировать третье измерение, т.к запрос такой наверное заказчик запрашивает не просто так, и структура данных уже требуется совершенно конкретная.

Конструкция ИЛИ в основном условии запроса -не всегда отключает индексы, но да, согласен, во многих случаях отключает и лучше так не делать.

Злоупотреблять временными таблицами я бы не стал. Они очень ресурсозатратные на этапе создания, особенно если туда выгружать пол-регистра)

Оптимизатор SQL очень умный. Я в последнее время в условиях соединения прописываю только условия соединения, а все остальное выношу в основное условие запроса ГДЕ. Это к последовательности обработки условий запроса оптимизатором. Вообще, в последний год ни одного случая нелепого разбора оптимизатором условий ГДЕ - не встречал. Постоянно перекидываю условия из/в соединений в ГДЕ, провожу очень много экспериментов, но - оптимизатор справляется на ура и сам понимает, где запустить nested loop а где index seek. Прозванивать запросы в консольке - обязательно, изучать планы запросов и принципы оптимизации - тоже.
39. biimmap 1381 08.08.23 09:40 Сейчас в теме
(38)
Прекрасно работают вложенные запросы, если их грамотно составить


Мне кажется, эта фраза является отличным поводом для написания статьи на эту тему.

Я в своей работе не использую анализ запросов. ЗУП довольно тяжёлая штука и особо там не соптимизируешь.
Но вот добавление вложенного запроса ВСЕГДА тормозит работу! Только если во вложенном запросе какая-то маленькая таблица.
Особенно это проявляется, если сервера дохлые) А это чудо мне регулярно попадается)))

Временные таблицы использую там, где запрос к регистру идёт несколько раз. Иногда для читабельности запроса.

Благодарю за аргументированный комментарий.
40. user1950534 08.08.23 11:28 Сейчас в теме
(39) Пожалуйста.

Ногами не пинайте, знаю что отчет по нулевым позициям с ссылкой на последний документ поступления можно и нужно сделать по-другому, но как говорится, для оправдания использования вложенных запросов, ЧИСТО технически. В плане запросов типовой "Консоли" 32 попугая. В регистре 1,8млн записей, позиций номенклатуры 7млн примерно

ВЫБРАТЬ
ВремЗапрос.НоменклатураСсылка.Код КАК КодНоменклатуры,
ВремЗапрос.НоменклатураСсылка.Наименование КАК НаименованиеНоменклатуры,
ВремЗапрос.НоменклатураСсылка.ВидНоменклатуры КАК ВидНоменклатуры,
ВремЗапрос.Период КАК Период,
ВремЗапрос2.ДвижениеПродукцииИМатериаловТоварыСсылка КАК ДвижениеПродукцииИМатериаловТоварыСсылка
ИЗ
(ВЫБРАТЬ
ТоварыНаСкладах.Номенклатура КАК НоменклатураСсылка,
ТоварыНаСкладах.Период КАК Период,
СУММА(ТоварыНаСкладах.ВНаличии) КАК СуммаВНаличии
ИЗ
РегистрНакопления.ТоварыНаСкладах КАК ТоварыНаСкладах
ГДЕ
ТоварыНаСкладах.Период > ДАТАВРЕМЯ(2023, 1, 1)

СГРУППИРОВАТЬ ПО
ТоварыНаСкладах.Номенклатура,
ТоварыНаСкладах.Период

ИМЕЮЩИЕ
СУММА(ТоварыНаСкладах.ВНаличии) = 0) КАК ВремЗапрос
ВНУТРЕННЕЕ СОЕДИНЕНИЕ (ВЫБРАТЬ
МАКСИМУМ(ТоварыНаСкладахСоединение.Период) КАК МаксПериод,
ДвижениеПродукцииИМатериаловТовары.Ссылка КАК ДвижениеПродукцииИМатериаловТоварыСсылка,
ДвижениеПродукцииИМатериаловТовары.Номенклатура КАК НоменклатураСсылка
ИЗ
РегистрНакопления.ТоварыНаСкладах КАК ТоварыНаСкладахСоединение
ЛЕВОЕ СОЕДИНЕНИЕ Документ.ДвижениеПродукцииИМатериалов.Товары КАК ДвижениеПродукцииИМатериаловТовары
ПО (ДвижениеПродукцииИМатериаловТовары.Ссылка = ТоварыНаСкладахСоединение.Регистратор)
И (ДвижениеПродукцииИМатериаловТовары.Номенклатура = ТоварыНаСкладахСоединение.Номенклатура)

ГДЕ ДвижениеПродукцииИМатериаловТовары.Ссылка.ХозяйственнаяОперация = &ОперацияПеремещениеИзФилиала

СГРУППИРОВАТЬ ПО
ДвижениеПродукцииИМатериаловТовары.Ссылка,
ДвижениеПродукцииИМатериаловТовары.Номенклатура) КАК ВремЗапрос2
ПО (ВремЗапрос.НоменклатураСсылка = ВремЗапрос2.НоменклатураСсылка)
И (ВремЗапрос.Период = ВремЗапрос2.МаксПериод)

upd: извиняюсь, забыл добавить условие ГДЕ во 2м вложенном запросе. Итог 0,9 попугаев. ЗЫ ХозяйственнаяОперация - не индексировалась)
Прикрепленные файлы:
41. Cерый 24 12.08.23 19:14 Сейчас в теме
Конструкцию ПОЛНОЕ СОЕДИНЕНИЕ использовать как можно реже, когда нет возможности решить задачу по-другому:
позволю себе возразить: FULL OUTER JOIN может вызывать появление дублирующих строк, но это можно предсказывать (на этапе разработки), выполняя для каждой соединяемой таблицы отдельный запрос с группировкой по ключу предполагаемого соединения с HAVING COUNT(*) > 1,
в случае существования строк на таких результатах можно анализировать причины отсутствия уникальности ключа, изменять его или готовить (хотя бы DISTINCT) таблицы перед соединением;
по крайней мере, это ПРЯМОЙ путь разработки, боюсь даже представить "решить задачу по-другому" - лишние сотни строк, скорее всего без SQL и каких-либо комментариев - мы ведь говорим о чужом коде, в котором автору все было понятно без слов?
42. biimmap 1381 12.08.23 19:23 Сейчас в теме
(41) Возражать можно сколько угодно... но есть стандарты разработки! На сколько я понял, написанное больше относится к написанию запросов на SQL, чем на 1С. Моя статья всё таки про 1С!

Самая большая проблема при использовании этого соединения совсем не в дублях строк! Она решается добавлением слова РАЗЛИЧНЫЕ после выбрать.

Основная проблема - это значения NULL! И от них возникает также много проблем, особенно у новичков.


(41)
боюсь даже представить "решить задачу по-другому"


Здесь как раз ничего страшного нет. Чаще всего можно сделать 2 таблицы и склеить их через ОБЪЕДИНИТЬ (ВСЕ).
Второй путь через левое соединение. Много раз встречал примеры, когда ПОЛНОЕ СОЕДИНЕНИЕ используются по ошибке вместо левого. Результирующая таблица содержит не дублирующие записи, а просто лишние! Меняешь соединение на ЛЕВОЕ и запрос правильно отрабатывает.
Cерый; +1 Ответить
43. Cерый 24 12.08.23 21:00 Сейчас в теме
LEFT JOIN также делает NULL ...
Кстати, делюсь: можно избегать вставлять текст запроса в программный код, обрамляя его символами с кодом 124 и удаляя их при каждом переносе в консоль запросов (или выхватывая текст запроса из отладчика), вставляя текст запроса в макет с типом "Текстовый документ" и извлекая его оттуда в коде:
Запрос = Новый Запрос;
Запрос.Текст = ПолучитьМакет("Запрос").ПолучитьТекст();
...
ТЗ = Запрос.Выполнить().Выгрузить();
aleksey2; +1 Ответить
Оставьте свое сообщение