Примеры запросов в 1С 8

Доброго времени суток, коллеги! Много раз на нашем сайте обсуждалась тема запросов в 1С, например, как получить всех родителей элемента справочника одним запросом. В этой статье вы увидите еще много разных примеров запросов, которые помогут вам решать повседневные задачи. Вот, посмотрите.

Содержание

  1. Как в запросе 1с8 установить условие проверки периода на конец дня?
  2. Как правильно обрабатывать значения NULL в запросе 1С8?
  3. Как вывести результат запроса в табличный документ?
  4. Как посчитать возраст по дате рождения в запросе 1С8?
  5. Почему в результате запроса 1С8 появляется ошибка «Ошибка чтения значения» при отладке?
  6. Как запросом получить все подчиненные документы?
  7. Как выглядит недокументированный синтаксис оператора ВЫБОР?
  8. Как составить запрос к табличной части документа?
  9. Как запросом для документа найти все подчинённые ему документы?
  10. Как сравнить строки в запросе?
  11. Как в запросе проверить поле на пустую ссылку?
  12. Как в запросе убрать фильтр на значение параметра?

Как в запросе 1с8 установить условие проверки периода на конец дня?

В запросе воспользуемся функцией КОНЕЦПЕРИОДА(&ДатаКонец, ДЕНЬ), она приведет дату к виду «23:59:59».

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

Как правильно обрабатывать значения NULL в запросе 1С8?

В запросе значения типа NULL образуются в результате соединений (ЛЕВОЕ, ПРАВОЕ), когда элементу из одной таблицы по условию не находится соответствующего элемента из другой. Значение типа NULL имею специфические особенности:

    • Cравнение значения NULL с любым другим аргументом всегда возвращает ложь. Например, если в запросе поле «Количество» возвращает NULL, то если использовать операции сравнения «<», «>», или «=» с числом 1000, то результатом всегда будет «Ложь». Даже, если сравнить с самим значением NULL, то все равно результатом будет «Ложь»:
ГДЕ
	ГТД.Количество = NULL
    • Применение арифметических операций к значению типа NULL всегда возвращает NULL. Например, если в запросе к полю «Количество», которое возвращает NULL, прибавить числовое значение или отнять от него числовое значение, то будет возвращено значение NULL:
	ГТД.Количество+300 КАК Поле1
    • Для определения значения NULL используется функция конструкция «IS NULL». Чтобы получить записи со значением NULL воспользуемся следующей конструкцией:
      ГДЕ
      	ГТД.Регистратор.Организация IS NULL
      

      если нужно получить записи без NULL, тогда:

      ГДЕ
      	НЕ ГТД.Регистратор.Организация IS NULL
      
    • Для преобразования типа NULL используется функция «isNULL» или «ЕСТЬNULL». Теперь можно сравнивать с полученным значением или применять к нему арифметические операции, не боясь за конечный результат:
	ЕСТЬNULL(ГТД.Количество, 0)+300 КАК Поле1
    • Для того, чтобы в результате запроса отсечь записи, содержащие значения NULL применяются следующие конструкции: «IS NOT NULL», «NOT <поле> is NULL»:
ГДЕ
	ГТД.Регистратор.Организация IS NOT NULL

или

ГДЕ
	NOT ГТД.Регистратор.Организация IS NULL

Как вывести результат запроса в табличный документ?

Для этого можно использовать объект ПостроительОтчета:

ТабДок = Новый ТабличныйДокумент;
Результат = РезультатЗапроса.Выгрузить();

Построитель = Новый ПостроительОтчета;
Построитель.ИсточникДанных = Новый ОписаниеИсточникаДанных(Результат);
Построитель.Вывести(ТабДок);

ТабДок.Записать("D:\mxl\Таблица.mxl");

Как посчитать возраст по дате рождения в запросе 1С8?

Использовать функцию языка запроса РАЗНОСТЬДАТ:

ВЫБРАТЬ
	Сотрудники.Сотрудник,
	Сотрудники.Пол,
	РАЗНОСТЬДАТ(Сотрудники.ДатаРождения, &ТекДата, ГОД) КАК Возраст
ИЗ
	Сотрудники КАК Сотрудники
		ПОЛНОЕ СОЕДИНЕНИЕ ПриемНаРаботу КАК ПриемНаРаботу
		ПО Сотрудники.Сотрудник = ПриемНаРаботу.Сотрудник
		ПОЛНОЕ СОЕДИНЕНИЕ Пенсия КАК Пенсия
		ПО Сотрудники.Сотрудник = Пенсия.Сотрудник

Почему в результате запроса 1С8 появляется ошибка «Ошибка чтения значения» при отладке?

Бывает, что в консоли запрос отрабатывается нормально, но в рабочем режиме падает с ошибкой «Значение не является значением объектного типа (Сумма)». При этом отладчик показывает, что в коллекции «ВыборкаИзРезультатаЗапроса» находиться сумма со значением «Ошибка чтения значения». При отладке выдается «Ошибка чтения значения», если в функции написать так:

Результат = Запрос.Выполнить();
Выборка = Результат.Выбрать();
Возврат Выборка;

Ошибка чтения значений результата запроса, возникает из-за того, что в выборке еще не осуществлена установка на первый элемент выборки. Для этого существует метод «Следующий()» коллекции «ВыборкаИзРезультатаЗапроса». Поэтому надо писать так:

Если Выборка.Следующий() Тогда
   ДоговорКонтрагента = Выборка.Наименование;
КонецЕсли;

Как запросом получить все подчиненные документы?

С помощью Функции «ПолучитьСписокВводимыхДокументовНаОсновании» получим список документов, которые вводятся на основании заданного документа:

//  Параметры: ДокументПоиска: Тип - Метаданные объекта
Функция ПолучитьСписокВводимыхДокументовНаОсновании(ДокументПоиска) Экспорт
	СписокДокументов = Новый СписокЗначений;
	Для Каждого Документ Из Метаданные.Документы Цикл
		Если Документ.ВводитсяНаОсновании.Содержит(ДокументПоиска) Тогда
			СписокДокументов.Добавить(Документ.Имя, Документ.Синоним);
		КонецЕсли;
	КонецЦикла;
	Возврат СписокДокументов;
КонецФункции

Теперь, на основании списка документов найдем все подчинённые заданному документу:

Функция ПолучитьПодчиненныеДокументы()	
	СписокЗаполнения = ПолучитьСписокВводимыхДокументовНаОсновании(СсылкаНаОбъект.Метаданные());
	ТекстЗапросаПоСтатусу = "";
	Для Каждого ЭлементСписка Из СписокЗаполнения Цикл
		Если НЕ ПустаяСтрока(ТекстЗапросаПоСтатусу) Тогда
			ТекстЗапросаПоСтатусу = ТекстЗапросаПоСтатусу + "
			|ОБЪЕДИНИТЬ ВСЕ
			|";
		КонецЕсли;		
		ТекстЗапросаПоСтатусу = ТекстЗапросаПоСтатусу + "
		|ВЫБРАТЬ " + ?(ПустаяСтрока(ТекстЗапросаПоСтатусу), "РАЗРЕШЕННЫЕ", "") + "
		| Док.Ссылка КАК ПодчиненныйДокумент
		|ИЗ
		| Документ." + ЭлементСписка.Значение + " КАК Док
		|ГДЕ
		| Док.ДокументОснование = &парамОснование
		| И Док.Проведен
		|";
	КонецЦикла;	
	
	Запрос = Новый Запрос;
	Запрос.УстановитьПараметр("парамОснование", СсылкаНаОбъект);
	Запрос.Текст = ТекстЗапросаПоСтатусу;
	
	Возврат Запрос.Выполнить().Выгрузить().ВыгрузитьКолонку("ПодчиненныйДокумент");	
КонецФункции // ПолучитьПодчиненныеДокументы()

Выведем полученные документы:

Процедура ВывестиПодчиненныеДокументы()
	Массив = ПолучитьПодчиненныеДокументы();
	Для каждого Эл Из Массив Цикл
		Сообщить(Эл);
	КонецЦикла;
КонецПроцедуры

Как выглядит недокументированный синтаксис оператора ВЫБОР?

Вот нестандартный вариант синтаксиса оператора ВЫБОР:

	ВЫБРАТЬ
	ВЫБОР ДЕНЬНЕДЕЛИ(ДАТАВРЕМЯ(2015, 4, 1))
		КОГДА 1
			ТОГДА "Понедельник"
		КОГДА 2
			ТОГДА "Вторник"
		КОГДА 3
			ТОГДА "Среда"
		КОГДА 4
			ТОГДА "Четверг"
		КОГДА 5
			ТОГДА "Пятница"
		КОГДА 6
			ТОГДА "Суббота"
		ИНАЧЕ "Воскресенье"
	КОНЕЦ КАК ДеньНедели

В этом примере показано, как с помощью опрератора ВЫБОР выводить текстовое представление дня недели.

Как составить запрос к табличной части документа?

Пример запроса:

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

Особенность этого запроса в том, что мы обращаемся к табличной части «Товары». Поэтому к реквизитам документа «ЧекККМ» мы обращаемся через свойство «Ссылка». Только в этом случае мы сможем получить строки табличной части документа. Если не указать свойство «Ссылка», то появится ошибка, примерно такого вида:

{(7, 5)}: Поле не найдено «Документ.ЧекККМ.Дата»

Как запросом для документа найти все подчинённые ему документы?

Воспользуемся следующим запросом:

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

Запрос.УстановитьПараметр("ДокументОснование",	Накладная);
РезультатЗапроса = Запрос.Выполнить();

Выборка = РезультатЗапроса.Выбрать();

Пока Выборка.Следующий() Цикл
	СФ = Выборка.Ссылка.ПолучитьОбъект();
	СФ.ДокументОснование = "";
	СФ.Записать(РежимЗаписиДокумента.Запись);
КонецЦикла;

Как сравнить строки в запросе?

|  ГДЕ  (Номер ПОДОБНО &НомерНакладной)
Запрос.УстановитьПараметр("НомерНакладной", "%"+НомерНакладной+"%");

Как в запросе проверить поле на пустую ссылку?

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

Заметим, что в параметре пишем «Документ», а не «Документы» и «ПустаяСсылка» без скобок.

Как в запросе убрать фильтр на значение параметра?

Например, нам нужно вывести данные о продажах, отфильтровав их по значению в поле формы «Товар», если в этом поле выбран нужный нам товар. И если товар не выбран, то вывести данные по всем товарам. Пример запроса такой:

Запрос = Новый Запрос;

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

Запрос.УстановитьПараметр("ДатаНачала", ДатаНачала);
Запрос.УстановитьПараметр("ДатаОкончания", ДатаОкончания);
Запрос.УстановитьПараметр("Товар", Товар);

Рассмотрим четыре способа, как избавится от фильтра в запросе.

  1. Изменим параметр запроса с помощью функции «СтрЗаменить»:
    Если Товар.Пустая() Тогда
    	Запрос.Текст = СтрЗаменить(Запрос.Текст, "&Товар", "");
    Иначе
    	Запрос.Текст = СтрЗаменить(Запрос.Текст, "&Товар", "Номенклатура = &Товар");
    КонецЕсли;
    
  2. В параметре виртуальной таблицы вместо значения «&Товар» запишем следующее выражение:
    |&Товар = ЗНАЧЕНИЕ(Справочник.Номенклатура.ПустаяСсылка) 
    | ИЛИ Номенклатура = &Товар
    

    Если параметр товар не заполнен, то первое выражение примет значение ИСТИНА, тогда значение всего выражения примет значение ИСТИНА. В этом случае как-будто и нет никакого фильтра. Но если товар заполнен, то первое выражение принимает значение ЛОЖЬ. Тогда сработает второе выражение и произойдет фильтрация по товару.

  3. Еще один способ возможен благодаря новому объекту платформы «СхемаЗапроса (QuerySchema)», который появился в версии 1С 8.3.5:
    СхемаЗапроса = Новый СхемаЗапроса;
    СхемаЗапроса.УстановитьТекстЗапроса(Запрос.Текст);
    Если ЗначениеЗаполнено(Товар) Тогда
    	СхемаЗапроса.ПакетЗапросов[0].Операторы[0].Источники[0].Источник.Параметры[3].Выражение = 
    	Новый ВыражениеСхемыЗапроса("Номенклатура = &Товар");
    КонецЕсли;
    Запрос.Текст = СхемаЗапроса.ПолучитьТекстЗапроса();
    
  4. Последний способ очень громоздкий, но его тоже можно использовать:
    Если Товар.Пустая() Тогда
    	Запрос.Текст =
    	"ВЫБРАТЬ
    	|	ПродажиОбороты.Номенклатура,
    	|	ПродажиОбороты.СуммаОборот КАК Сумма
    	|ИЗ
    	|	РегистрНакопления.Продажи.Обороты(&ДатаНачала, 
    	|	&ДатаОкончания, , ) КАК ПродажиОбороты"
    Иначе
    	Запрос.Текст =
    	"ВЫБРАТЬ
    	|	ПродажиОбороты.Номенклатура,
    	|	ПродажиОбороты.СуммаОборот КАК Сумма
    	|ИЗ
    	|	РегистрНакопления.Продажи.Обороты(&ДатаНачала, 
    	|	&ДатаОкончания, , Номенклатура = &Товар) КАК ПродажиОбороты";
    КонецЕсли;
    

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

ПОДПИСКА