Вложенные запросы в списке источников

Язык запросов

Синтаксис и применение Вложенные запросы в списке источников в платформе 1С:Предприятие. Описание и примеры кода.

Полное описание, параметры и ограничения

Вложенные запросы в списке источников

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

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

Пример:

Выбрать
Ссылка, Номенклатура, Количество

Из
(
Выбрать Первые 8
Ссылка, Номенклатура, Количество

Из
Документ.РасходнаяНакладная.Состав
)
Как ВложенныйЗапрос

Результат запроса:

Ссылка

Номенклатура

Количество

Расходная накладная 00007 от 25.02.2002 21:03:21

Джинсы женские

4

Расходная накладная 00006 от 25.02.2002 0:00:00

Джинсы женские

5

Расходная накладная 00006 от 25.02.2002 0:00:00

Рубашка "Ковбойка"

5

Расходная накладная 00005 от 01.03.2002 20:58:28

Джинсы женские

1

Расходная накладная 00004 от 01.03.2002 20:50:40

Джинсы женские

1

Расходная накладная 00003 от 23.02.2002 0:00:00

Мойдодыр "Аквариум"

5

Расходная накладная 00003 от 23.02.2002 0:00:00

Раковина "Лилия"

8

Расходная накладная 00003 от 23.02.2002 0:00:00

Смеситель "Ультра"

10

Практические примеры

Различить уникальные коды, уникальные строки и сохранение дублей при объединении

Один код 1 имеет две разные подписи, а пара 1/Книга повторяется трижды в двух списках. РАЗЛИЧНЫЕ сравнивает все выбранные поля; ОБЪЕДИНИТЬ ВСЕ сохраняет каждую исходную строку.

Где и как запускать

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

Подготовка

  1. В отдельной учебной базе 8.5.1.1343 создайте общий модуль УчебныйЯзык: Сервер=Истина, Глобальный=Ложь, ВызовСервера=Ложь, Привилегированный=Ложь. Клиентские и внешнее соединение отключены; ПовторноеИспользованиеВозвращаемыхЗначений=НеИспользовать.

  2. Вставьте весь приведённый текст в этот общий модуль. ВыполнитьПример — экспортная точка входа; остальные процедуры и функции располагаются рядом, а не внутри неё.

  3. В своей внешней учебной обработке создайте управляемую форму, команду Выполнить и кнопку. Клиентский обработчик Выполнить(Команда) вызывает свою процедуру ВыполнитьНаСервере(); она имеет директиву &НаСервереБезКонтекста и одну строку УчебныйЯзык.ВыполнитьПример();. Это серверный вызов общего модуля, а не разрешение клиенту прямо обращаться к серверной библиотеке.

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

  5. HTML только показывает BSL. Код в 1С не запускался; перечисленные результаты и отрицательные опыты проверяйте самостоятельно в собственном стенде.

  6. Весь исходный состав задан в модуле. Нужна только серверная учебная обработка по общей подготовке; метаданные документов и справочников не требуются.

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

  8. Каждый исходный код целый положительный, каждая подпись строка до 40 символов. Это не данные и не ключи из рабочих систем.

Процедура ВыполнитьПример() Экспорт
    Первый = СоздатьСвоюТаблицу();
    Второй = СоздатьСвоюТаблицу();
    НоваяСтрока = Первый.Добавить();
    НоваяСтрока.Код = 1;
    НоваяСтрока.Название = "Книга";
    НоваяСтрока = Первый.Добавить();
    НоваяСтрока.Код = 1;
    НоваяСтрока.Название = "Книга";
    НоваяСтрока = Первый.Добавить();
    НоваяСтрока.Код = 1;
    НоваяСтрока.Название = "Книга другая";
    НоваяСтрока = Первый.Добавить();
    НоваяСтрока.Код = 2;
    НоваяСтрока.Название = "Ручка";
    НоваяСтрока = Второй.Добавить();
    НоваяСтрока.Код = 1;
    НоваяСтрока.Название = "Книга";
    НоваяСтрока = Второй.Добавить();
    НоваяСтрока.Код = 3;
    НоваяСтрока.Название = "Блокнот";
    Если Первый.Количество() <> 4 Или Второй.Количество() <> 2 Тогда
        ВызватьИсключение "Изменились собственные исходные списки";
    КонецЕсли;
    Менеджер = Новый МенеджерВременныхТаблиц;
    Попытка
        Создание = Новый Запрос;
        Создание.МенеджерВременныхТаблиц = Менеджер;
        Создание.Текст = "ВЫБРАТЬ Первый.Код КАК Код, Первый.Название КАК Название
        |ПОМЕСТИТЬ ВТСвойПервыйСписок
        |ИЗ &Первый КАК Первый;
        |
        |ВЫБРАТЬ Второй.Код КАК Код, Второй.Название КАК Название
        |ПОМЕСТИТЬ ВТСвойВторойСписок
        |ИЗ &Второй КАК Второй";
        Создание.УстановитьПараметр("Первый", Первый);
        Создание.УстановитьПараметр("Второй", Второй);
        Создание.ВыполнитьПакет();
        Запрос = Новый Запрос;
        Запрос.МенеджерВременныхТаблиц = Менеджер;
        Запрос.Текст = "ВЫБРАТЬ РАЗЛИЧНЫЕ Первый.Код КАК КодОбразца
        |ИЗ ВТСвойПервыйСписок КАК Первый
        |УПОРЯДОЧИТЬ ПО КодОбразца";
        Коды = Запрос.Выполнить().Выгрузить();
        Если Коды.Количество() <> 2 Тогда
            ВызватьИсключение "Ожидались два собственных уникальных кода";
        КонецЕсли;
        Сообщить(Коды[0].КодОбразца = 1 И Коды[1].КодОбразца = 2);
        Запрос.Текст = "ВЫБРАТЬ РАЗЛИЧНЫЕ Первый.Код КАК КодОбразца, Первый.Название КАК НаименованиеОбразца
        |ИЗ ВТСвойПервыйСписок КАК Первый
        |УПОРЯДОЧИТЬ ПО КодОбразца, НаименованиеОбразца";
        ПолныеСтроки = Запрос.Выполнить().Выгрузить();
        ПроверитьСвойСостав(ПолныеСтроки, 3, 1, 1, 1, 0);
        Запрос.Текст = "ВЫБРАТЬ Первый.Код КАК КодОбразца, Первый.Название КАК НаименованиеОбразца
        |ИЗ ВТСвойПервыйСписок КАК Первый
        |ОБЪЕДИНИТЬ
        |ВЫБРАТЬ Второй.Код КАК ДругойКод, Второй.Название КАК ДругаяПодпись
        |ИЗ ВТСвойВторойСписок КАК Второй
        |УПОРЯДОЧИТЬ ПО КодОбразца, НаименованиеОбразца";
        Объединение = Запрос.Выполнить().Выгрузить();
        Сообщить("ОБЪЕДИНИТЬ");
        ПроверитьСвойСостав(Объединение, 4, 1, 1, 1, 1);
        Сообщить(Объединение.Колонки.Найти("КодОбразца") <> Неопределено);
        Сообщить(Объединение.Колонки.Найти("ДругойКод") = Неопределено);
        Запрос.Текст = "ВЫБРАТЬ Первый.Код КАК КодОбразца, Первый.Название КАК НаименованиеОбразца
        |ИЗ ВТСвойПервыйСписок КАК Первый
        |ОБЪЕДИНИТЬ ВСЕ
        |ВЫБРАТЬ Второй.Код КАК ДругойКод, Второй.Название КАК ДругаяПодпись
        |ИЗ ВТСвойВторойСписок КАК Второй
        |УПОРЯДОЧИТЬ ПО КодОбразца, НаименованиеОбразца";
        Объединение = Запрос.Выполнить().Выгрузить();
        Сообщить("ОБЪЕДИНИТЬ ВСЕ");
        ПроверитьСвойСостав(Объединение, 6, 3, 1, 1, 1);
        Сообщить(Объединение.Колонки.Найти("КодОбразца") <> Неопределено);
        Сообщить(Объединение.Колонки.Найти("ДругойКод") = Неопределено);
        Запрос.Текст = "ВЫБРАТЬ Объединённые.КодОбразца КАК КодОбразца, КОЛИЧЕСТВО(*) КАК Повторений
        |ИЗ (
        |ВЫБРАТЬ Первый.Код КАК КодОбразца, Первый.Название КАК НаименованиеОбразца
        |ИЗ ВТСвойПервыйСписок КАК Первый
        |ОБЪЕДИНИТЬ ВСЕ
        |ВЫБРАТЬ Второй.Код КАК ДругойКод, Второй.Название КАК ДругаяПодпись
        |ИЗ ВТСвойВторойСписок КАК Второй
        |) КАК Объединённые
        |СГРУППИРОВАТЬ ПО Объединённые.КодОбразца
        |УПОРЯДОЧИТЬ ПО КодОбразца";
        Частоты = Запрос.Выполнить().Выгрузить();
        Если Частоты.Количество() <> 3 Тогда
            ВызватьИсключение "Ожидались три собственные группы";
        КонецЕсли;
        Сообщить(Частоты[0].КодОбразца = 1 И Частоты[0].Повторений = 4);
        Сообщить(Частоты[1].КодОбразца = 2 И Частоты[1].Повторений = 1);
        Сообщить(Частоты[2].КодОбразца = 3 И Частоты[2].Повторений = 1);
    Исключение
        Менеджер.Закрыть();
        ВызватьИсключение;
    КонецПопытки;
    Менеджер.Закрыть();
КонецПроцедуры

Функция СоздатьСвоюТаблицу()
    Источник = Новый ТаблицаЗначений;
    Источник.Колонки.Добавить("Код", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(5, 0, ДопустимыйЗнак.Неотрицательный)));
    Источник.Колонки.Добавить("Название", Новый ОписаниеТипов("Строка", , Новый КвалификаторыСтроки(40)));
    Возврат Источник;
КонецФункции

Процедура ПроверитьСвойСостав(Таблица, ОжидалосьВсего, ОжидалосьКниг, ОжидалосьДругихКниг, ОжидалосьРучек, ОжидалосьБлокнотов)
    Если Таблица.Количество() <> ОжидалосьВсего Тогда
        ВызватьИсключение "Число собственных строк не совпало";
    КонецЕсли;
    Книги = Таблица.НайтиСтроки(Новый Структура("КодОбразца,НаименованиеОбразца", 1, "Книга"));
    ДругиеКниги = Таблица.НайтиСтроки(Новый Структура("КодОбразца,НаименованиеОбразца", 1, "Книга другая"));
    Ручки = Таблица.НайтиСтроки(Новый Структура("КодОбразца,НаименованиеОбразца", 2, "Ручка"));
    Блокноты = Таблица.НайтиСтроки(Новый Структура("КодОбразца,НаименованиеОбразца", 3, "Блокнот"));
    Если Книги.Количество() <> ОжидалосьКниг Или ДругиеКниги.Количество() <> ОжидалосьДругихКниг
        Или Ручки.Количество() <> ОжидалосьРучек Или Блокноты.Количество() <> ОжидалосьБлокнотов Тогда
        ВызватьИсключение "Полный состав собственных строк не совпал";
    КонецЕсли;
    Сообщить("Проверен полный состав строк, всего " + Строка(ОжидалосьВсего));
КонецПроцедуры

Разбор по шагам

  1. Создать свои два типизированных списка: четыре строки слева и две справа. Первая таблица содержит два полных дубля 1/Книга и отдельную строку 1/Книга другая.

  2. Передать оба списка параметрами, создать две приватные временные таблицы собственного менеджера.

  3. РАЗЛИЧНЫЕ только по коду даёт два кода 1 и 2. Добавление подписи меняет идентичность строки: уникальных пар первого списка уже три.

  4. ОБЪЕДИНИТЬ без ВСЕ оставляет четыре разные пары двух списков: одинаковая 1/Книга одна, 1/Книга другая остаётся отдельной.

  5. ОБЪЕДИНИТЬ ВСЕ даёт все шесть строк: пара 1/Книга встречается трижды. Это не ошибка и не исправление данных.

  6. Обе ветви имеют два поля одного смысла в одинаковом порядке. Имена результата берутся из первой ветви; ДругойКод второй ветви не создаёт новую колонку.

  7. Использовать объединение как вложенный источник в скобках и обратиться к его выведенному полю КодОбразца через псевдоним Объединённые.

  8. Сгруппировать шесть строк по коду: частоты 4,1,1. Порядок результатов задаётся явно, а полный состав пар проверяется независимо от сортировки строковых подписей.

  9. Закрыть свой менеджер в обоих исходах; рабочие документы/регистры не читать и не изменять.

Как проверить результат

  1. Уникальных кодов первого списка два, уникальных полных строк три.

  2. Без ВСЕ четыре полные строки; с ВСЕ шесть, из них три одинаковые пары 1/Книга.

  3. Колонка КодОбразца присутствует, колонка ДругойКод отсутствует в обеих объединённых выборках.

  4. Вложенный источник даёт частоты по кодам 4,1,1; сумма частот равна шести.

Ожидаемый результат

Дубли разобраны по полному составу собственных строк, а объединение и вложенный источник показаны в законченном серверном модуле.

На что обратить внимание

  1. РАЗЛИЧНЫЕ не означает уникальность только первого поля: сравнивается вся выбранная строка.

  2. Смена ОБЪЕДИНИТЬ ВСЕ на ОБЪЕДИНИТЬ может потерять значимые повторения. Это не универсальный способ исправить неверный отчёт.

  3. Объединение добавляет строки, соединение связывает источники по условию. В этом уроке нет СОЕДИНЕНИЕ.

  4. Число полей обеих ветвей должно совпадать; поля сопоставляются по позиции, не по псевдониму второй ветви.

  5. Разные типы соответствующих полей дают составной тип. Здесь типы намеренно совпадают, другие типы этим опытом не проверены.

  6. Для РАЗЛИЧНЫЕ выражения сортировки должны входить в список выборки; старую совместимость 8.1 не используйте как обход ограничения.

  7. Проверки Python моделируют только полностью заданные строки, а не запуск запросов в 1С.

Пример не запускался в вашей базе. Перед применением проверьте его в указанном учебном контексте.

Не хотите разбираться сами?

Адаптируем это решение под вашу базу. Оценка бесплатно.

Оставить задачу

1С, 1С:Предприятие — товарные знаки ООО «1С». Сайт не является официальным представительством фирмы «1С» и не аффилирован с ней.