Добавил:
sora.alai.102@gmail.com Делаю работы на заказ. Какие именно? Пишите. Или регайтесь на бирже, где я работаю: https://vsesdal.com/promo?ref=748568 Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Хрусталева Е. Ю. Язык запросов 1С-Предприятия 8 (2013)

.pdf
Скачиваний:
2183
Добавлен:
25.11.2018
Размер:
31.3 Mб
Скачать

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

Результат запроса (см. рис. 1.83), использующего соединение таблиц, будет аналогичен выполнению предыдущего запроса, использующего разыменование полей ссылочного типа.

Как получить данные из разных таблиц, не связывая, а дополняя их

При выборке данных с помощью запросов бывает необходимо дополнить данные, получившиеся в результате выполнения одного запроса, данными другого запроса. Например, можно дополнить информацию из приходных накладных со структурой (Контрагент, Товар, Количество, Цена) данными из расходных накладных с такой же структурой.

Для этого в языке запросов существует возможность объединения нескольких запросов. При этом записи, полученные с помощью каждого из объединяемых запросов, собираются в один результат запроса. При объединении каждый запрос получает данные независимо, то есть у каждого из запросов – свое описание выбираемых полей (ВЫБРАТЬ), источников запроса (ИЗ), условий отбора (ГДЕ), полей группировки (СГРУППИРОВАТЬ ПО). Затем данные, получаемые в результате каждого запроса, объединяются, и уже над этим объединением выполняются такие операции, как упорядочивание результатов

(УПОРЯДОЧИТЬ ПО) и расчет итогов (ИТОГИ ПО).

Для объединения запросов используется предложение ОБЪЕДИНИТЬ, которое располагается в секции Объединение запросов текста запроса. Все секции запроса приведены на рис. 1.13.

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

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

(листинг 1.86).

Листинг 1.86. Объединение данных о заказах товаров клиентами и данных о продажах товаров этим клиентам

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

Названия полей результата запроса описываются в списке полей выборки первого из объединяемых запросов. Поля выборки второго запроса сопоставляются с полями результата в соответствии с порядком их следования в списке полей выборки.

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

Клиент документа ЗаказТовара и поле Покупатель документа РасходнаяНакладная из объединяемых запросов также принадлежат к этому типу.

Результат выполнения запроса представлен на рис. 1.84.

Рис. 1.84. Объединение данных о заказах товаров клиентами и данных о продажах товаров этим клиентам

В общем случае могут объединяться результаты выполнения сразу нескольких запросов.

По умолчанию при объединении запросов полностью одинаковые строки в результате запроса, сформированные разными запросами, заменяются одной. Если требуется, чтобы были оставлены разные строки, необходимо указать ключевое слово ВСЕ.

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

Временные таблицы и пакетные запросы

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

Запрос, служащий источником данных, является вложенным, а запрос, который эти данные использует, является основным или внешним.

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

Казалось бы, в этом нет ничего особенно сложного. Свяжем левым соединением таблицы справочника Товары и документа ПриходнаяНакладная по ссылкам товаров и выведем требуемые поля из обеих таблиц. При этом упорядочим результат запроса по наименованиям товаров в порядке иерархии справочника (листинг 1.87).

Листинг 1.87. Вывод всех товаров в порядке иерархии справочника «Товары» с данными об их поступлении

Результат выполнения запроса представлен на рис. 1.85.

Рис. 1.85. Вывод всех товаров в порядке иерархии справочника «Товары» с данными об их поступлении

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

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

Листинг 1.88. Вывод всех товаров в порядке иерархии справочника «Товары» с данными об их поступлении за ноябрь

Мы видим, что результат запроса – несколько не такой, как мы ожидали (рис. 1.86).

Рис. 1.86. Вывод товаров, поступавших в ноябре, из справочника «Товары»

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

Вэтом и в некоторых других случаях выходом из ситуации является использование вложенного запроса в качестве источника внешнего запроса. Поэтому предыдущий запрос можно переписать следующим образом (1.89).

Листинг 1.89. Вывод всех товаров в порядке иерархии справочника «Товары» с данными об их поступлении за ноябрь

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

(рис. 1.87).

Рис. 1.87. Вывод всех товаров в порядке иерархии справочника «Товары» с данными об их поступлении за ноябрь

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

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

Подробнее

Документация «1С:Предприятие 8.3. Руководство разработчика», раздел 8.2 «Язык запросов», а также встроенная справка Справка > Содержание справки > 1С:Предприятие > Встроенный язык > Работа с запросами > Выполнение и работа с запросами во встроенном языке > Работа с временными таблицами.

Дополним текст вложенного запроса из предыдущего запроса предложением ПОМЕСТИТЬ, которое располагается сразу после списка полей выборки (листинг 1.90).

Листинг 1.90. Помещение данных о поступлениях товаров за ноябрь во временную таблицу

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

ИНДЕКСИРОВАТЬ ПО.

подробнее

«Эффективное использование индексов. Пример 5».

Чтобы увидеть данные, помещенные во временную таблицу, в консоли запросов нужно нажать кнопку Выполнить запрос с временными таблицами рядом с кнопкой Выполнить (рис. 1.88).

Рис. 1.88. Данные временной таблицы «ПоступлениеТоваров»

Итак, в результате выполнения запроса (листинг 1.90) мы поместили данные о поступлениях товаров за ноябрь во временную таблицу с именем ПоступлениеТоваров.

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

помощью менеджера временных таблиц (этот вариант мы рассмотрим позже в разделе "Использование временных таблиц с помощью встроенного языка"), либо с помощью пакетного запроса. Этот вариант мы и рассмотрим сейчас.

Пакетный запрос содержит последовательность запросов, разделенных символом «;» (точка с запятой). При выполнении пакетного запроса входящие в него запросы выполняются друг за другом. При этом если при выполнении одного из запросов была создана временная таблица, то следующие за ним запросы при их выполнении могут использовать данные этой временной таблицы.

Необходимо учитывать, что временные таблицы будут существовать до окончания исполнения всего пакета запроса или до исполнения в пакете запроса, уничтожающего данную временную таблицу с помощью конструкции УНИЧТОЖИТЬ.

Подробнее

Документация «1С:Предприятие 8.3. Руководство разработчика», раздел 8.2 «Язык

запросов», а также встроенная справка Справка > Содержание справки > 1С:Предприятие > Встроенный язык > Работа с запросами > Выполнение и работа с запросами во встроенном языке > Работа с пакетными запросами.

Таким образом, разобьем запрос, содержащий вложенный запрос (см. листинг 1.89), на два запроса и объединим их в один пакетный запрос (листинг 1.91).

Листинг 1.91. Вывод всех товаров в порядке иерархии справочника «Товары» с данными об их поступлении за ноябрь

В первом запросе мы помещаем данные о поступлении товаров за ноябрь во временную таблицу с именем ПоступлениеТоваров. Затем следует символ «;» (точка с запятой), который указывает на то, что это – пакетный запрос. В следующем запросе справочник

товаров связывается левым соединением с временной таблицей по ссылкам товаров, и в итоге мы получаем результат, аналогичный результату при выполнении запроса, содержащего вложенный запрос (см. рис. 1.87).

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

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

подробнее

Раздел «Не использовать соединения с вложенными запросами и с виртуальными таблицами».

Пример, показывающий использование вложенного запроса для ограничения значений выборки в условии отбора (раздел «Как использовать данные одного запроса внутри другого запроса»), также можно переделать с использованием временной таблицы вместо вложенного запроса.

В заключение покажем, как можно переписать запрос, выполняющий несколько соединений нескольких таблиц (раздел «Как получить данные из разных таблиц, связанных несколькими соединениями») с использованием временной таблицы (листинг

1.92).

Листинг 1.92. Два варианта запроса, выполняющего несколько соединений данных нескольких таблиц

Второй вариант, использующий временную таблицу, более понятен, по крайней мере полезен для изучения. Так как если выполнить сначала только первую часть запроса (помещающую данные во временную таблицу), а затем – весь запрос целиком, то можно поэтапно проследить, какие данные получаются в результате каждого соединения (рис. 1.89).

Рис. 1.89. Левое соединение данных справочника «Товары» и данных таблиц остатков и оборотов товаров