Как в 1С запросе с INNER JOIN оставить 1 строку из правой таблицы?

База знаний Одина — Одинэсника Форумы ODIN — Форум по 1С Предприятию Как в 1С запросе с INNER JOIN оставить 1 строку из правой таблицы?

Просмотр 1 ветки ответов
  • Автор
    Сообщения
    • #35665
      Телеграм группа https://t.me/odineskiOdineski
      Участник

        запрос со внутренним соединением . Как оставить 1 строку в правой таблице, если из несколько

      • #35666
        bot_avaOdin — Одинэсник
        Участник

          Шура, привет!

          Если у тебя есть запрос с внутренним соединением (INNER JOIN) и в правой таблице несколько строк, а нужно оставить только одну (например, первую по какому-то критерию), то в 1С запросах это можно сделать несколькими способами.

          Самый распространённый и универсальный способ — использовать подзапрос с ограничением количества строк (например, через ВЫБРАТЬ ПЕРВЫЕ 1) или агрегатную функцию, либо использовать конструкцию с РАНГ() или ПЕРВЫЕ 1 в подзапросе.

          Пример: допустим, есть таблица Документ.Заказы (левая) и Таблица с деталями Заказа (правая), и в деталях несколько строк на один заказ, а нужно к заказу присоединить только одну строку из деталей.

          Вариант с подзапросом:

          Запрос.Текст = 
          "ВЫБРАТЬ
          |	Заказы.Ссылка КАК Заказ,
          |	Детали.НужноеПоле
          |ИЗ
          |	Документ.Заказы КАК Заказы
          |	ВНУТРЕННЕЕ СОЕДИНЕНИЕ
          |	(
          |		ВЫБРАТЬ ПЕРВЫЕ 1
          |		|	ДеталиВнутр.СсылкаНаЗаказ,
          |		|	ДеталиВнутр.НужноеПоле
          |		|ИЗ
          |		|	Документ.ДеталиЗаказа КАК ДеталиВнутр
          |		|	ГДЕ ДеталиВнутр.СсылкаНаЗаказ = Заказы.Ссылка
          |		|	УПОРЯДОЧИТЬ ПО ДеталиВнутр.ДатаУбывания
          |	) КАК Детали
          |ПО Заказы.Ссылка = Детали.СсылкаНаЗаказ";
          

          Обрати внимание, что в подзапросе мы выбираем ПЕРВЫЕ 1 строку из правой таблицы для каждого заказа, упорядочивая по нужному полю (например, дате).

          Если платформа 1С не поддерживает такой подзапрос с корреляцией (ссылка на внешний запрос), то можно сделать так:

          1. Сначала сформировать временную таблицу с нужными строками из правой таблицы, где для каждой группы (например, по заказу) выбрать только одну строку (через агрегатные функции или РАНГ()).

          2. Затем сделать внутреннее соединение с этой временной таблицей.

          Пример с использованием РАНГ():

          Запрос.Текст =
          "ВЫБРАТЬ
          |	Заказы.Ссылка КАК Заказ,
          |	Детали.НужноеПоле
          |ИЗ
          |	Документ.Заказы КАК Заказы
          |	ВНУТРЕННЕЕ СОЕДИНЕНИЕ
          |	(
          |		ВЫБРАТЬ
          |			ДеталиВнутр.СсылкаНаЗаказ,
          |			ДеталиВнутр.НужноеПоле,
          |			РАНГ() ПО (ДеталиВнутр.ДатаУбывания) КАК Ранг
          |		ИЗ
          |			Документ.ДеталиЗаказа КАК ДеталиВнутр
          |	) КАК Детали
          |ПО Заказы.Ссылка = Детали.СсылкаНаЗаказ
          |ГДЕ Детали.Ранг = 1";
          

          Здесь мы нумеруем строки в деталях по дате и выбираем только с рангом 1 — то есть первую строку.

          Если в твоей версии 1С нет функции РАНГ(), то можно сделать через агрегатные функции:

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

          — Затем соединить с правой таблицей по этому минимальному значению, чтобы получить только одну строку.

          Пример:

          Запрос.Текст =
          "ВЫБРАТЬ
          |	Заказы.Ссылка КАК Заказ,
          |	Детали.НужноеПоле
          |ИЗ
          |	Документ.Заказы КАК Заказы
          |	ВНУТРЕННЕЕ СОЕДИНЕНИЕ
          |	(
          |		ВЫБРАТЬ
          |			ДеталиВнутр.СсылкаНаЗаказ,
          |			МИНИМУМ(ДеталиВнутр.ДатаУбывания) КАК МинДата
          |		ИЗ
          |			Документ.ДеталиЗаказа КАК ДеталиВнутр
          |		СГРУППИРОВАТЬ ПО
          |			ДеталиВнутр.СсылкаНаЗаказ
          |	) КАК МинДаты
          |ПО Заказы.Ссылка = МинДаты.СсылкаНаЗаказ
          |	ВНУТРЕННЕЕ СОЕДИНЕНИЕ
          |	Документ.ДеталиЗаказа КАК Детали
          |ПО МинДаты.СсылкаНаЗаказ = Детали.СсылкаНаЗаказ
          |	И МинДаты.МинДата = Детали.ДатаУбывания";
          

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

          Если нужна помощь с конкретным примером — пиши, могу помочь составить запрос.

          Если кратко — чтобы оставить одну строку из нескольких в правой таблице при внутреннем соединении, нужно либо:

          — Использовать подзапрос с ПЕРВЫЕ 1 и сортировкой,

          — Использовать РАНГ() и фильтрацию по рангу = 1,

          — Использовать агрегатные функции (МИНИМУМ, МАКСИМУМ) и дополнительное соединение.

          Все зависит от версии платформы и конкретной задачи.

          Если нужна помощь с кодом — могу написать пример под твой случай.

      Просмотр 1 ветки ответов
      • Для ответа в этой теме необходимо авторизоваться.
      База знаний 1С