Инструменты пользователя

Инструменты сайта


1c:база:запросы

Запросы

Описание

Запросы представляют собой, табличную модель доступа к данным. С помощью запросов удобно организовывать чтение данных, по той причине, что с помощью одного запроса (здесь читаем обращения к серверу) можно в большинстве случаев получить все необходимые для работы данные. В случае с объектной моделью доступа(работа с классом Справочник.Выборка), при получении каждого элемента в переборе система будет обращаться к серверу. В том случае если база 1С работает под управлением СУБД (клиент-серверный вариант) использование запросов является более оптимальным, потому что работа СУБД ориентирована на использование запросов. Результатом запроса всегда является одна таблица за исключением специфических случаев (например в случае пакетного запроса).

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

Виды таблиц

Таблицы в 1С делятся на реальные и виртуальные. Реальные таблицы, это те которые действительно существуют в базе данных. Виртуальные таблицы в базе не существуют, и представляют по сути, функции которые возвращают определенным образом отфильтрованные данные из реальных таблиц. Эти таблицы сделаны для удобства разработчиков. У виртуальных таблиц могут быть параметры. Для таблиц оборотов регистра накопления к примеру можно указать дату начала и дату окончания выборки оборотов. А для таблицы остатков этого же регистра, можно указать только дату, на которую будут получены остатки. Для этой таблицы можно указать условие (этим условием может быть отдельный запрос) и тогда будет наложен фильтр с указанным условием.

Если используется какое-либо условие при обращении к виртуальной таблице, необходимо указывать его в параметрах виртуальной таблицы, а не на закладке «Условия». Так как если указать условие в параметрах фильтр будет наложен в момент выполнения запроса к реальной таблице, а если указать в условии, то данные сначала будут получены, в полном объеме а уже потом наложен фильтр. В некоторых случаях такой запрос может оказаться просто "неподъемным" для сервера.

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

Запрос = Новый Запрос
// и далее можно указать текст запроса, параметры и тд
Запрос.Текст = "ВЫБРАТЬ Номенклатура.Ссылка ИЗ Справочник.Номенклатура КАК Номенклатура"

Основной синтаксис языка запросов.

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

Таблицы и поля

Любой запрос начинается с выражения «Выбрать» или Select, далее следуют перечисление полей которые вы хотите видеть в запросе и источник откуда будут браться эти поля как в запросе выше, в качестве источника могут быть как таблицы базы данных, так и связи этих таблиц. Если в запросе создаются временные таблицы, после перечисления полей должно стоять ключевое слово "Поместить" и имя временной таблицы.

Группировка строк запроса.

При формировании запроса очень часто бывает необходимо "свернуть" данные запроса, то есть к примеру у нас в результате выборки получились такие записи

  1. Петров 100
  2. Иванов 200
  3. Иванов 400
  4. Сидоров 90
  5. Петров 150

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

  1. Петров 250
  2. Иванов 600
  3. Сидоров 90

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

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

Условие и параметры в запросе

На результат выборки запроса, можно накладывать условия, которые могут быть достаточно разнообразными, в качестве условия могут выступать строковые или числовые константы, значения перечислений, предопределенные элементы справочников, подзапросы или любое значение переданное в параметре запроса. Для того, что бы указать, что выражение является параметром, перед ним указывают символ "&". За указание условия в запросе, отвечает секция "ГДЕ"

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

Передать параметр в запрос, можно следующим образом:

Запрос.УстановитьПараметр("ИмяПараметра", ЗначениеПараметра);

Псевдонимы

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

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

Объединения

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

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

Соединения

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

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

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

  • Декартово произведение, или cross join, такое соединение получается если не указывать какой тип связи нам нужен, система для каждой таблицы создаст набор записей, например если в одной таблице было 7 записей а во второй 12 в результате запроса вы получите 7 * 12 = 84 то есть все комбинации которые можно составить из этих данных. Забыв указать тип соединения и объединив таблицы с несколькими десятками тысяч записей(регистр остатков товара в небольшой базе) можно создать при выполнении запроса и выводе результата серьезную нагрузку на базу.
  • Внутреннее соединение или inner join(галочка "ВСЕ" не стоит не слева, не справа), необходимо использовать тогда когда из двух таблиц нужно получить только те данные которые совпадают по условию связи в обоих таблицах.
  • Левое соединение или left inner join (галочка "ВСЕ" стоит слева) – в результат запроса попадают все записи которые находятся в левой таблице, и те записи из правой таблицы которые отвечают условию связи.
  • Правое соединение или right inner join тоже самое что и левое соединение, только в результат попадают все записи из таблицы справа(галочка "ВСЕ" стоит справа), следует отметить, что 1С старается придерживаться левого соединения и если вы попробуете настроить правое соединение, с помощью конструктора, при нажатии на кнопку ОК, она поменяет местами таблицы и сделает левое соединение.
  • Полное соединение или full outer join (галочка "ВСЕ" стоит и слева и справа) в запрос попадут все записи из обоих таблиц, которые 1С попытается сопоставить с помощью условия связи.

Вложенные запросы

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

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

Сортировка

Если необходимо упорядочить результаты запроса, такое поведение, можно настроить на закладке конструктора Порядок, на этой закладке, можно перечислить список полей по которым нужно производить сортировку или можно в тексте запроса указать конструкцию "УПОРЯДОЧИТЬ ПО" и перечислить поля по которым необходимо производить сортировку. Также доступно выражение "АВТОУПОРЯДОЧИВАНИЕ", с помощью которого для ссылочных типов данных происходит сортировка по представлению ссылки.

Тип данных NULL

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

  • ЕСТЬNULL(ПроверяемоеЗначение, ЗначениеКотороеНадоВернутьЕслиВПроверяемомЗначенииNULL) выражение вернет либо первое значение, либо второе если первое NULL, удобно использовать в полях выходной таблицы
  • ЕСТЬ NULL(ЗначениеТипаNULL) выражение возвращает либо Истина, либо Ложь.
  • ЕстьNULL FIXME не могу вспомнить как юзать, помню что возвращает ИСТИНА если NULL слева.

Использование функций

Язык запросов обладает ограниченным набором функций, для обработки данных, так как считается, что запросы это средство для получения данных, а не для их обработки. Но необходимый минимум, все таки имеется. Например нет возможность получить дату без времени, но есть возможность привести дату к началу дня, месяца, года, с помощью функции, начало периода. Условный оператор тоже присутствует в виде функции "Выбор". Функция "Значение" позволяет в запросе получать значения перечислений, и к некоторым значениям системных перечислений(например вид движения регистра) или значений предопределенных значений справочника. Описание функций языка запросов, отсутствует во встроенном синтаксис помощнике, но его можно найти в справке которая находится в меню «Справка» или по кнопке F1. Там нужно открыть содержание справки (можно сразу его открывать из этого же меню, или по shift F1) и выбрать Встроенный язык – Работа с запросами – Синтаксис языка запросов – Ключевые слова и функции – Функции.

Получение данных из табличных частей документов

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

	Запрос.Текст = 
	"ВЫБРАТЬ
	|	ОтчетОРозничныхПродажах.Товары.(
	|		Номенклатура
	|	)
	|ИЗ
	|	Документ.ОтчетОРозничныхПродажах КАК ОтчетОРозничныхПродажах";

А вот так будет правильно:

	Запрос.Текст = 
	"ВЫБРАТЬ
	|	ОтчетКомитентуОПродажахТовары.Номенклатура
	|ИЗ
	|	Документ.ОтчетКомитентуОПродажах.Товары КАК ОтчетКомитентуОПродажахТовары";

Разумеется в любом случае нужно наложить условие на поле "Ссылка" что бы не получить в результате запроса табличные части всех существующих в системе документов.

Только авторизованные участники могут оставлять комментарии.
1c/база/запросы.txt · Последнее изменение: 2020/10/01 03:34 — admin