Как объединить в 1с столбцы
Войдите как ученик, чтобы получить доступ к материалам школы
Язык запросов 1С 8.3 для начинающих программистов: объединение
Автор уроков и преподаватель школы: Владимир Милькин
Объединение в запросах
В языке запросов имеется возможность объединять несколько запросов. При этом записи, полученные с помощью каждого из объединяемых запросов, будут собраны в один результат запроса.
Как всегда начнём с примера.
Пусть требуется написать запрос, который возвращает все названия цветов и вкусов в одной таблице.
Цвета мы умеем выбирать так:
А вот, чтобы объединить эти два результата в один как раз и потребуется операция объединения:
Обратите внимание на то, что операция объединения вовсе не гарантирует, что элементы будут идти в каком-то определённом порядке. В общем случае они могут следовать друг за другом как угодно, поэтому если важен порядок необходимо как и всегда указывать его явно (через секцию УПОРЯДОЧИТЬ).
Требования к запросам, участвующим в объединении
У объединяемых запросов должно быть одинаковое количество полей . Иначе мы получим такую ошибку:
В объединяемых запросах соответствующие друг другу (по порядку) поля должны иметь одинаковый тип . Но это требование, в отличие от предыдущего, не является обязательным. Если соответствующие друг другу поля имеют разный тип, то поле результата будет иметь СОСТАВНОЙ тип, который разбирался нами на одном из прошлых уроков:
Несмотря на то, что поле первого запроса имеет тип СТРОКА, а второго ЧИСЛО, нам удалось объединить их в одну таблицу. Но тип результатирующего поля стал составным и нам придётся учитывать это в дальнейшем. Вы читаете ознакомительную версию урока, полноценные уроки находятся здесь.
Кстати, вы заметили, что поле итоговой таблицы (после объединения) называется Наименование, а не Калорийность? Эта такое правило : поля итоговой таблицы всегда имеют названия совпадающие с именами описанными в первом из объединяемых запросов.
Объединение более двух запросов
При объединении каждый запрос собирает данные независимо, а уже затем результаты объединяются в один. Количество объединяемых запросов не ограничено.
Напишем объединение трёх запросов:
Повторяющиеся строки
Давайте объединим один и тот же запрос сам с собой:
Обратите внимание на то, что мы объединили две одинаковые таблицы цветов, а в результате каждый цвет встречается ровно один раз.
Всё потому, что по умолчанию при объединении запросов полностью одинаковые строки в результате запроса, заменяются одной. Вы читаете ознакомительную версию урока, полноценные уроки находятся здесь.
Если требуется, чтобы были оставлены в том числе одинаковые строки (дубли), необходимо указать ключевое слово ВСЕ:
Упорядочивание при объединении
Пытаться отдельно упорядочивать результаты запросов, участвующих в объединении не имеет смысла. Поэтому при попытке написать:
Упорядочивать можно только результат объединения :
Обратите внимание на то, что секция УПОРЯДОЧИТЬ ПО в данном случае относится не к последнему запросу, а уже к результату объединения запросов.
Подведение итогов при объединении
Пытаться отдельно подводить итоги по запросам, участвующим в объединении, также не имеет смысла. Поэтому при попытке написать:
Подводить итоги можно только по результату объединения :
Обратите внимание на то, что секция ИТОГИ ПО в данном случае относится не к последнему запросу, а уже к результату объединения запросов.
Рабочий пример
Давайте решим такую задачу. Требуется вывести для каждого элемента справочника Еда закупленное и проданное количество за весь период.
Поступление еды у нас в базе происходит документом ПоступлениеЕды. У документа есть табличная часть Еда, с реквизитами Номенклатура и Количество.
Сначала выберем все строки табличной части Еда из всех поступлений:
Теперь сгруппируем этот результат по еде с суммированием количества:
Аналогичным образом получим продажу еды из документов ПродажаЕды:
Осталось объединить эти два запроса:
Обратите внимание на то, как мы дополнили оба запроса ещё одним полем СУММА(0). Мы вынуждены были сделать это, так как оба запроса содержат по два поля, а объединение запросов должно содержать три поля. Вы читаете ознакомительную версию урока, полноценные уроки находятся здесь. Если бы мы не сделали этого, а написали просто:
Войдите как ученик, чтобы получить доступ к материалам школы
Система компоновки данных 1С 8.3 для начинающих: объединяем наборы данных
Автор уроков и преподаватель школы: Владимир Милькин
На прошлом уроке мы познакомились с соединением наборов данных. Сегодня же мы научимся объединять различные наборы данных в один набор.
Ставим цель
- Создать новый отчёт, в котором будут выводиться закупки (дата, поставщик) и продажи (дата, клиент) одновременно.
- Для этого сделаем два отдельных набора данных с выборкой из таблиц документов "ПоступлениеЕды" и "ПродажаЕды", а затем объединим их в один набор.
Создаем новый отчет
Открываем базу "Гастроном" в конфигураторе и через главное меню "Файл->Новый. " создаём отчёт:
Вид документа - "Внешний отчет":
В форме нового отчёта указываем имя "Урок7" и нажимаем кнопку "Открыть схему компоновки данных":
Соглашаемся с именем макета по умолчанию:
Создаем первый набор данных
Создаём новый набор данных - запрос (через зелёный плюсик), выделяем его и вызываем конструктор запроса:
Делаем выборку из таблицы документов "ПоступлениеЕды" следующих полей:
Вот он, текст нашего запроса к таблице по закупкам:
Создаем второй набор данных
Выделяем мышкой пункт "Наборы данных".
. и добавляем ещё один набор данных - запрос:
Выделяем его и вызываем конструктор запроса:
Делаем выборку из таблицы документов "ПродажаЕды" следующих полей:
Текст запроса будет таким:
Сделаем имена более читабельными. Для этого двойным щелчком переименуем "НаборДанных1" в "Покупки" и поле "Дата" в "ДатаПокупки":
Второй же набор "НаборДанных2" переименуем в "Продажи", а поле "Дата" переименуем в "ДатаПродажи":
Мы получили два набора данных. В первом - информация по покупкам (дата покупки и поставщик), во втором- информация по продажам (дата продажи и клиент). Давайте попробуем теперь вывести всё это в отчет.
Проверяем результат
Переходим на закладку "Настройки" и нажимаем волшебную палочку для вызова конструктора:
Тип отчета - "Список. ":
Выбираем поля для отчёта из обоих наборов:
Сохраняем отчёт и формируем в режиме пользователя:
Получилось не совсем то, что ожидали. Получилось перекрёстное соединение одного набора данных с другим. А нам нужно именно объединение. Исправим.
Создаем объединение наборов данных
Для этого переходим на закладку "Наборы данных".
Снова выделяем мышкой пункт "Наборы данных".
. и добавляем туда набор данных - объединение:
Видим, что этот набор добавился и у него совершенно другая картинка (не таблица, как у двух других, а два объединяющихся круга):
Затем перетаскиваем мышкой наборы "Покупки" и "Продажи" в "НаборДанных1":
Вот это и значит, что теперь "Покупки" и "Продажи" будут не соединяться, а именно объединяться в отчёте.
Сохраним отчёт и сформируем в режиме пользователя:
Отлично. То, что надо.
А давайте зададимся целью объединить столбцы "Поставщик" и "Клиент" в один? И пусть этот новый столбец будет называться "Контрагент".
Для этого заходим на закладку "Наборы данных" и меняем имя поля "Поставщик" в наборе "Покупки" на имя "Контрагент":
Затем в наборе "Продажи" меняем имя поля "Клиент" на имя "Контрагент":
Переходим на закладку "Настройки", выделяем пункт "Отчет", переходим внизу на закладку "Выбранные поля", удаляем уже не существующие поля "Поставщик" и "Клиент" и перетаскиваем из первой колонки во вторую новое поле "Контрагент":
Должно получится вот так:
Готово
Сохраняем отчёт и проверяем в режиме пользователя:
Замечательно всё получилось.
Войдите на сайт как ученик
Для учеников
Прибегайте к изучению эталонного варианта только после самостоятельного выполнения всех шагов.
На вопросы учеников — отвечаю по почте, но прежде загляните в ЧАВО (ссылка) .
Язык запросов 1С позволяет сделать соединения двух и более таблиц. Под соединением понимается состыковка двух таблиц по ключевым полям.
Всего 4 вида соединений
- Полное соединение — в результате получается одна таблица, содержащая все выбранные колонки, обычно число строк равняется количеству совпадающих по ключам строк плюс все несовпадающие.
- Левое соединение — на выходе будет выбранные поля обеих таблиц (полностью первой и совпадающие по ключам соединения второй), количество строк всегда больше или равно количеству в первой таблице (условие соединения может вызывать дубли, если в правой таблице поля соединения дублируются))
- Правое соединение — обратное левому (главная таблица вторая).
- Внутреннее соединение — количество строк такой таблице равно количеству совпадающих по условию объединения строк.
Возможно выборка всех полей объединяемых таблиц (обращение к ним по псевдониму), но если соединение не внутреннее, то в отсутствующем поле будет значение NULL, поэтому следует рассматривать его особым образом или подменять значение через функцию ЕстьNULL().
Условием соединения может быть и простое условие «ИСТИНА», которое соединит таблицы с значительным увеличением количества строк (каждая строка соединится с каждой строкой второй таблицы).
Различные виды объединений используются для своих своих задач и целей:
Левое, когда требуется к одной основной таблице добавить какие-то свойства из другой. Например к списку контрагентов добавить задолженность, банковские реквизиты, фио руководителей.
При формировании такого запроса, следует добиться отсутствия в правой таблице дублей строк, этому способствует использование временных таблиц или вложенных. В противном случае в левой таблице появятся дубли контрагентов, что будет мешать верному восприятию.
Если задвоения будут в динамическом списке, это может вызвать ошибку дублирования ключевого поля.
Внутреннее соединение служит для максимально ограничения выборки, например: получить контрагентов у которых были реализации в выбранный период.
В управлении торговлей для решения такой задачи соединение не так уж важно, достаточного было бы обратится к регистру «Продажи», а вот в «Бухгалтерии предприятия» соединение будет более верным решением: ведь мы не знаем заранее какой счет учета используется для продажи, могут быть созданные пользователем субсчета (это даст более короткое решение, но все зависит от ситуации — не обязательно же оно должно быть универсальным).
При необходимости соединения более двух таблиц производится цепочка соединений — сначала производится первое соединение, а с результатом производится соединение последующих таблиц.
Требование к таким таблицам:
- различные их псевдонимы и непересечение имен ключей и таблиц.
- При множественных соединениях допустимо комбинация нескольких видов соединений.
Как задать соединение в конструкторе запроса:
Шаг 1: выберите необходимые таблицы, которые возможно соединить
- Это производится на вкладке таблицы конструктора запроса.
- Далее можно сразу выбрать нужные поля.
Шаг 2: Переходим на вкладку «Связи»
- Для простых таблиц, где явно определяются связи, система их объединит самостоятельно
- В данном случае левое соединение
- Чтобы получить внутреннее: снимаются оба флажка «Все» — тогда в таблицу попадут только контрагенты у которых есть контактные лица
- Чтобы получить полное: устанавливаются оба флажка
- Если требуется соединение по двум условиям добавляется еще одна строка связи.
Вид соединения задается соответствующим словом перед «СОЕДИНЕНИЕ», остальной синтаксис идентичен. Правое не рассматриваем, так как конструктор запроса автоматически поменяет таблицы местами и сделает левое соединение.
Пример текста запроса «Внутреннее соединение»:
ВЫБРАТЬ
Контрагенты . Ссылка ,
КонтактныеЛица . Ссылка КАК КонтактноеЛицо
ИЗ
Справочник . Контрагенты КАК Контрагенты
ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник . КонтактныеЛица КАК КонтактныеЛица
ПО Контрагенты . ОсновноеКонтактноеЛицо = КонтактныеЛица . Ссылка
И ( Контрагенты . ЮрФизЛицо = ЗНАЧЕНИЕ ( Перечисление . ЮрФизЛицо . ЮрЛицо )
Пример левого соединения
ВЫБРАТЬ
Контрагенты . Ссылка ,
КонтактныеЛица . Ссылка КАК КонтактноеЛицо
ИЗ
Справочник . Контрагенты КАК Контрагенты
ЛЕВОЕ СОЕДИНЕНИЕ Справочник . КонтактныеЛица КАК КонтактныеЛица
ПО Контрагенты . ОсновноеКонтактноеЛицо = КонтактныеЛица . Ссылка
И ( Контрагенты . ЮрФизЛицо = ЗНАЧЕНИЕ ( Перечисление . ЮрФизЛицо . ЮрЛицо )
Пример «полного соединения»
ВЫБРАТЬ
Контрагенты . Ссылка ,
КонтактныеЛица . Ссылка КАК КонтактноеЛицо
ИЗ
Справочник . Контрагенты КАК Контрагенты
ПОЛНОЕ СОЕДИНЕНИЕ Справочник . КонтактныеЛица КАК КонтактныеЛица
ПО Контрагенты . ОсновноеКонтактноеЛицо = КонтактныеЛица . Ссылка
И ( Контрагенты . ЮрФизЛицо = ЗНАЧЕНИЕ ( Перечисление . ЮрФизЛицо . ЮрЛицо )
На что следует обратить внимание:
- Как уже было сказано на пустые значения при левом или полном соединении.
- С осторожностью используйте полные соединения и срезы последних из регистров, это может сильно замедлить выборку.
- При использовании конструктора обращайте внимание на соединяемые таблицы иногда он может подставить в левую таблицу не ожидаемое вами, если это упустить вначале придется затем исправлять руками или через правое (одна секунда внимания сбережет время в дальнейшем).
- Если вы выберете 2 таблицы, но не укажите связи, то получится неявное полное соединение (таблицы будут через «запятую»). Пример:
ВЫБРАТЬ
Контрагенты . Ссылка ,
КонтактныеЛица . Ссылка КАК КонтактноеЛицо
ИЗ
Справочник . Контрагенты КАК Контрагенты ,
Справочник . КонтактныеЛица КАК КонтактныеЛица
Сворачивать рекламу, чтобы сберечь деньги, все равно, что останавливать часы, чтобы сберечь время.
— Э.Макензи , 14 фраз
В отличии от соединения таблиц, объединение производит присоединение данных к таблице с абсолютно одинаковым количеством колонок.
Возможно 2 варианта объединения:
При этом не производятся никакие проверки — это простая операция:
- Значения полей могут быть различного типа.
- Если количество полей различно, система выдаст ошибку — «Разное количество полей объединяемых в запросах».
- Первая таблица считается главной — именно из нее берутся имена полей результирующей выборки (конструктор удаляет псевдонимы, если они присутствуют, автоматически).
- Нет явного ограничения количества таких объединений.
Внешний вид объединения в конструкторе запросов:
Добавляются эти запросы на вкладке «Объединение/Псевдонимы»
Здесь же можно управлять режимом объединения (флажки «Без дублей»):
При добавлении поля в одну из таких таблиц (в режиме конструктора), в остальные таблицы добавляется значение NULL — автоматического подбора по именам источника не происходит. В этом случае приходится подредактировать текст запроса руками.
Если в объединении присутствуют неопределенное или пустые поля, такая процедура может происходить не полностью (режим ОБЪЕДИНИТЬ) — не все строки включаются в результат. Такое было замечено однократно, возможно, было связано с какой-то версией платформы, либо с использованием агрегирующих функции запроса.
Объединение больших выборок может влиять на производительность запроса: так как ведётся поиск дублей строк.
Об идеалах нации можно судить по ее рекламе.
— Норман Дуглас
Defor Что-то вроде FAQ Отзывов (5) В закладки
Имеем отчет вида:
Необходимо одинаковые заголовки группировок объединить.
Предлагаю данную операцию произвести над сформированным табличным документом, используя следующий код:
Вставляем вызов после формирования табличного документа:
Результат представлен ниже:
Главный недостаток этого способа, трудно заранее определить начальную и конечную область поиска, т. к. функция может отработать и объединить любые другие смежные идентичные ячейки. Если есть идеи как однозначно идентифицировать ячейки заголовка группировок пишите. А пока этот код можно использовать с некоторыми изменения в каждом конкретном случае.
Большое спасибо за обработку, тоже самое приходилось делать на 7-ке.
Может я спроше глупость но куда вставить данную процедуру?
Платформа 8.2. Форма отчета управляемая, использую выше приведенные процедуры/функции в отчете следующим образом:
Модуль формы отчета:
&НаКлиенте
// Проверка двух смежных ячеек на идентичночность
Функция ОбъединятьЯчейки(ТабДок, индСтр, индКол)
Ячейка = ТабДок.Область(индСтр, индКол);
ЯчейкаСлед = ТабДок.Область(индСтр, индКол+1);
Если ПустаяСтрока(Ячейка.Текст) Тогда
Возврат ложь
ИначеЕсли Ячейка.Текст = ЯчейкаСлед.Текст //Проверяем на соответствие заголовка
и Ячейка.Имя = “R”+индСтр+”C”+индКол Тогда // Проверяем на соответствие имени (отсеиваем уже объединенные ячейки)
Возврат Истина;
Иначе
Возврат ложь
КонецЕсли;
&НаКлиенте
// Обработка заголовков таблицы
//
// Параметры
// Табл – – Табличный документ формы
Процедура ОбработатьЗаголовки(ТабДок)
ОбъединяемаяОбласть = Неопределено;
Для индСтр=1 По 11 Цикл//ТабДок.ВысотаТаблицы Цикл //Для оптимизации здесь нужно будет ограничить высоту таблицы
НачальнаяКолонка = 0;
Для индКол=1 По ТабДок.ШиринаТаблицы Цикл
Если ОбъединятьЯчейки(ТабДок, индСтр, индКол) Тогда // определяем начало объединения
Если не НачальнаяКолонка Тогда
НачальнаяКолонка = индКол;
КонецЕсли;
ИначеЕсли НачальнаяКолонка Тогда // завершаем объединение
ТекстЗаголовка = ТабДок.Область(индСтр, индКол).Текст;
ОбъединяемаяОбласть = ТабДок.Область(индСтр, НачальнаяКолонка, индСтр, индКол);
ОбъединяемаяОбласть.Объединить();
ОбъединяемаяОбласть.ГоризонтальноеПоложение = ГоризонтальноеПоложение.Центр;
ОбъединяемаяОбласть.Текст = ТекстЗаголовка;
НачальнаяКолонка = 0;
Иначе
НачальнаяКолонка = 0;
КонецЕсли;
КонецЦикла;
//Если не ОбъединяемаяОбласть = Неопределено Тогда // Если нашли в строке области для объединения, то прекращаем дальнейшие поиски
// возврат;
//КонецЕсли;
&НаКлиенте
Процедура ФайловыйВариант()
&НаСервере
Процедура КлиентСерверныйВариант()
&НаКлиенте
Процедура Сформировать(Команда)
// Вставить содержимое обработчика.
Проблема следующая шапка отчета выводится без объединения заголовка. При этом если процедуру КлиентСерверныйВариант() скомпоновать на кленте (&НаКлиенте), то всё объединяется как надо. Происходит как-будто затирание табличного документа серверным таб. доком. Ещё раз, после возврата с сервера происходит обработка таб.дока, но на клиенте всё равно таб.док. без объединения. Решил вынести компиляцию процедуры КлиентСерверныйВариант() на сервер, т.е. все процессы СКД протекают на сервере, а результат Таб. док. обрабатывается уже на клиенте в итоге происходит как-будто затерание обработанного результата. Подскажите в чем причина? Пробывал вынести выше приведенные процедуры/функции обработки табличного документа в модуль объекта отчета в процедуру ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка) без результатно, ставил сообщалки всё нормально, т.е. исполнение кода проходит как надо, но результат заголовок таблицы без объединения.
Читайте также: