Особенности языка запросов 1С.

01.04.14

Разработка - Запросы

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

На инфостарте уже есть несколько статей о языке запросов, после прочтения наиболее популярных них, например:
//infostart.ru/public/80366/
//infostart.ru/public/158617/
//infostart.ru/public/165456/

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

1. Конструкция "ИЗ".

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

ВЫБРАТЬ Справочник.Банки.*

 Выбирает все поля из справочника Банки. И является аналогичным запросу:

ВЫБРАТЬ
	Банки.*
ИЗ
	Справочник.Банки КАК Банки

 2. Упорядочивание данных по ссылочному полю

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

ВЫБРАТЬ
	Партия.Ссылка КАК Ссылка,
	Партия.Организация,
	Партия.Контрагент
ИЗ
	Документ.Партия КАК Партия

УПОРЯДОЧИТЬ ПО Ссылка

АВТОУПОРЯДОЧИВАНИЕ

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

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

ВЫБРАТЬ
	Партия.Ссылка КАК Ссылка,
	Партия.Организация,
	Партия.Контрагент
ИЗ
	Документ.Партия КАК Партия

УПОРЯДОЧИТЬ ПО 
  Партия.Дата,
  Партия.Номер

3.Получение текстового представления ссылочного типа. Конструкция "ПРЕДСТАВЛЕНИЕ". 

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

ВЫБРАТЬ
	Партия.Ссылка КАК Ссылка,
 ПРЕДСТАВЛЕНИЕ(Партия.Организация) КАК Организация, 
 ПРЕДСТАВЛЕНИЕ(Партия.Контрагент) КАК Контрагент
ИЗ
	Документ.Партия КАК Партия

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

4. Условие на выборку данных по шаблону.

Например, вам необходимо получить мобильные телефоны сотрудников вида (8 -123- 456-78-912). Для этого необходимо поставить такое условие в запросе:

ВЫБРАТЬ
	Сорудник.Наименование,
	Сорудник.Телефон КАК Телефон
ИЗ
	Справочник.Сотрудники КАК Сотрудники
ГДЕ
	Телефон ПОДОБНО "_-___-___-__-__"

Символ "_" является служебным и заменяет любой символ.

5.  Одновременное использование итогов и группировок.


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

ВЫБРАТЬ
	ОказаниеУслуг.Организация КАК Организация,
	ОказаниеУслуг.Номенклатура КАК Номенклатура,
	СУММА(ОказаниеУслуг.СуммаДокумента) КАК СуммаДокумента
ИЗ
	Документ.ОказаниеУслуг КАК ОказаниеУслуг

СГРУППИРОВАТЬ ПО
	ОказаниеУслуг.Организация,
	ОказаниеУслуг.Номенклатура
ИТОГИ ПО
	ОБЩИЕ,
	Организация,
	Номенклатура

В этом случае запрос вернет практически тоже самое что и такой запрос:

ВЫБРАТЬ
        ОказаниеУслуг.Организация КАК Организация,
        ОказаниеУслуг.Номенклатура КАК Номенклатура,
        ОказаниеУслуг.СуммаДокумента КАК СуммаДокумента
ИЗ
        Документ.ОказаниеУслуг КАК ОказаниеУслуг
ИТОГИ
        СУММА(СуммаДокумента)
ПО
        ОБЩИЕ,
        Организация,
        Номенклатура

Только первый запрос свернет записи с одинаковой номенклатурой.

6. Разыменование полей.

Обращение к полям через точку называется операцией разыменования ссылочного поля. Например Оплата.Организация.АдминистративнаяЕдиница. В этом случае в ссылочном поле "Организация" документа "Оплата", ссылается на  другую таблицу "Организации", в которой будет получено значение реквизита "АдминистративнаяЕдиница". Важно понимать, что при обращении к полям через точку платформа неявно создает подзапрос и соединяет эти таблицы.

Запрос:

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

Можно представить в виде:

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

При разыменовании ссылочных полей составного типа платформа пытается создать неявные соединения со  всеми таблицами, которые входят в тип этого поля. В этом случае запрос будет неоптимален.Если четко известно, какого типа поле, необходимо ограничивать такие поля по типу конструкцией ВЫРАЗИТЬ()

Например имеется регистр накопления "Нераспределенные оплаты", где регистратором могут выступать несколько документов. В этом случае неверно получать значения реквизитов регистратора таким образом: 

ВЫБРАТЬ 
   НераспределенныеОплаты.Регистратор.Дата,
   .....
ИЗ 
   РегистрНакопления.НераспределеныеОплаты КАК НераспределенныеОплаты

следует ограничить тип составного поля регистратор:

ВЫБРАТЬ 
  ВЫРАЗИТЬ(НераспределенныеОплаты.Регистратор КАК Документ.Оплата).Дата,
   .....
ИЗ 
   РегистрНакопления.НераспределеныеОплаты КАК НераспределенныеОплаты

7. Конструкция "ГДЕ"

При левом соединении двух таблиц, когда вы накладываете условие "ГДЕ" на правую таблицу то мы получим результат аналогичный результату при внутреннем соединении таблиц.

Пример. Необходимо выбрать всех Клиентов из Справочника клиенты и  для тех клиентов, у которых имеется документ оплата со значением реквизита "Организация" = &Организация вывести документ "Оплата", для тех у кого нет, не выводить.

Запрос:

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

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

ВЫБРАТЬ
	Оплата.Ссылка КАК Оплата,
	Оплата.Пайщик КАК Клиент
ПОМЕСТИТЬ тОплаты
ИЗ
	Документ.Оплата КАК Оплата
ГДЕ
	Оплата.Отделение = &Отделение
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
	Клиенты.Ссылка КАК Клиент,
	ЕСТЬNULL(тОплаты.Оплата, "") КАК Оплата
ИЗ
	Справочник.Клиенты КАК Клиенты
		ЛЕВОЕ СОЕДИНЕНИЕ тОплаты КАК тОплаты
		ПО Клиенты.Ссылка = тОплаты.Клиент

Можно обойти это условие и другим способом. необходимо наложить условие "ГДЕ" непосредственно в связи двух таблиц. Пример:

ВЫБРАТЬ
	Клиенты.Ссылка,
	Оплата.Ссылка
ИЗ
	Справочник.УС_Абоненты КАК УС_Абоненты
		ЛЕВОЕ СОЕДИНЕНИЕ Документ.Оплата КАК Оплата
		ПО (Клиенты.Ссылка = Оплата.Клиент
				И Оплата.Клиент.Наименование ПОДОБНО "Сахарный Пакет")

СГРУППИРОВАТЬ ПО
	Клиенты.Ссылка,
	Оплата.Ссылка


8. Соединения с Вложенными и Виртуальными таблицами

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

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

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

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

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

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

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

Виртуальные таблицы , позволяют получить практически готовые данные для большинства прикладных задач.(СрезПервых,СрезПоследних,Остатки,Обороты,ОстаткиИОбороты) Ключевое слово здесь виртуальные. Эти таблицы не являются физическими, а компонуются системой налету, т.е. при получении данных из виртуальных таблиц система собирает данные из итоговых таблиц регистров, компонует, группирует и выдает пользователю.

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

ВЫБРАТЬ
	Клиенты.Ссылка КАК Ссылка
ПОМЕСТИТЬ тКлиенты
ИЗ
	Справочник.Клиенты КАК Клиенты

ИНДЕКСИРОВАТЬ ПО
	Ссылка
ГДЕ
  Клиенты.Ссылка В (&Клиенты)
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
	НераспределенныеОплаты.СуммаОстаток,
	НераспределенныеОплаты.Клиент КАК Клиент
ПОМЕСТИТЬ тОстатки
ИЗ
	РегистрНакопления.НераспределенныеОплаты.Остатки( ,
			Клиент В
				(ВЫБРАТЬ
					тКлиенты.Ссылка
				ИЗ
					тКлиенты)) КАК НераспределенныеОплатыОстатки
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
	тКлиенты.Ссылка,
	тОстатки.СуммаОстаток КАК СуммаОстаток
ИЗ
	тКлиенты КАК тКлиенты
		ЛЕВОЕ СОЕДИНЕНИЕ тОстатки КАК тОстатки
		ПО тКлиенты.Ссылка = тОстатки.Клиент

9.Проверка результата выполнения запроса.

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

резЗапроса = Запрос.Выполнить();
Если резЗапроса.Пустой() Тогда 
    Возврат;
КонецЕсли;

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

10. Запросы в цикле.

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

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

Для Каждого Строка ИЗ ТаблицаКлиенты Цикл
	
	Запрос.УстановитьПараметр("Клиент", Клиент);  
	РезультатЗапроса = Запрос.Выполнить().Выбрать();	
			
КонецЦикла;

Это избавит систему от синтаксической проверки запроса в цикле.

11. Конструкция "ИМЕЮЩИЕ".

 

Конструкция, довольно редко встречающаяся в запросах. Позволяет накладывать условия на значения агрегатные функций (СУММА, МИНИМУМ, СРЕДНЕЕ и т.д.). Например, вам необходимо выбрать только тех клиентов, у которых сумма оплат в сентябре была больше 13 000 рублей. Если использовать условие "ГДЕ", то придется сначала создавать временную таблицу или вложенный запрос, там группировать записи по сумме оплаты и потом накладывать условие. Конструкция "ИМЕЮЩИЕ" поможет этого избежать.

ВЫБРАТЬ
	Оплата.Клиент,
	СУММА(Оплата.Сумма) КАК Сумма
ИЗ
	Документ.Оплата КАК Оплата
ГДЕ
	МЕСЯЦ(Оплата.Дата) = 9

СГРУППИРОВАТЬ ПО
	Оплата.Клиент

ИМЕЮЩИЕ
	СУММА(Оплата.Сумма) > 13000

В конструкторе для этого достаточно перейти на вкладку "Условия", добавить новое условие и поставить галочку на "Произвольное". Далее просто написать Сумма(Оплата.Сумма) > 13000 


12. Значение NULL

Я не буду описывать здесь принципы трехзначной логики в БД, есть множество статей на эту тему. Просто вкратце о том как NULL может повлиять на результат запроса. Значение NULL на самом деле не значение, а факт того, что значение не определено, неизвестно. Поэтому любые операции с NULL возвращают NULL, будь то сложение, вычитание, деление или сравнение. Значение NULL не может быть сравнимо со значением NULL, потому как мы не знаем, что именно сравнивать. Т.е. оба этих сравнения: NULL = NULL, NULL<>NULL - это не Истина или не Ложь, это неизвестно.

Давайте рассмотрим пример.

Нам необходимо для тех клиентов, у которых нет оплат, вывести поле "Признак" со значением "Нет оплат". Причем мы точно знаем, что такие клиенты у нас есть. И для того, чтобы отразить суть того, что писал выше сделаем это так.

ВЫБРАТЬ
	"Нет оплат" КАК Признак,
	NULL КАК Документ
ПОМЕСТИТЬ тОплаты
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
	Клиенты.Ссылка КАК Клиент,
	Оплата.Ссылка КАК Оплата
ПОМЕСТИТЬ тКлиентОплата
ИЗ
	Справочник.Клиенты КАК Клиенты
		ЛЕВОЕ СОЕДИНЕНИЕ Документ.Оплата КАК Оплата
		ПО Клиенты.Ссылка = Оплата.Пайщик
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
	тКлиентОплата.Клиент
ИЗ
	тКлиентОплата КАК тКлиентОплата
		ВНУТРЕННЕЕ СОЕДИНЕНИЕ тОплаты КАК тОплаты
		ПО тКлиентОплата.Оплата = тОплаты.Документ

Обратите внимание на вторую временную таблицу тКлиентОплата. Левым соединением я выбираю всех клиентов и все оплаты по этим клиентам. Для тех же клиентов у которых нет оплат в поле "Оплата" будет NULL . Следуя логике, в первой временной таблице "тОплаты" я обозначил 2 поля, одно из них NULL, второе строка "Не имеет оплат". В третьей таблице я соединяю внутренним соединением таблицы "тКлиентОплата" и "тОплаты" по полям "Оплата" и "Документ". Мы знаем, что в первой таблице поле "Документ" это NULL, и во второй таблице у тех, у кого нет оплат в поле "Оплата" тоже NULL. Что же вернет нам такое соединение? А ничего не вернет. Потому как сравнение NULL = NULL не принимает значение Истина.

Для того, чтобы запрос вернул нам ожидаемый результат, перепишем его:

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

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
	Клиенты.Ссылка КАК Клиент,
	ЕСТЬNULL(Оплата.Ссылка, ЗНАЧЕНИЕ(Документ.Оплата.ПустаяСсылка)) КАК Оплата
ПОМЕСТИТЬ тКлиентОплата
ИЗ
	Справочник.Клиенты КАК Клиенты
		ЛЕВОЕ СОЕДИНЕНИЕ Документ.Оплата КАК Оплата
		ПО Клиенты.Ссылка = Оплата.Пайщик
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
	тКлиентОплата.Клиент
ИЗ
	тКлиентОплата КАК тКлиентОплата
		ВНУТРЕННЕЕ СОЕДИНЕНИЕ тОплаты КАК тОплаты
		ПО тКлиентОплата.Оплата = тОплаты.Документ

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

 

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

13. Недокументированная особенность конструкции "ВЫБОР КОГДА...ТОГДА....КОНЕЦ".

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

ВЫБРАТЬ
	ВЫБОР
		КОГДА Пользователи.Наименование = "Вася Пупкин"
			ТОГДА "Наш любимый сотрудник"
		ИНАЧЕ "Не знаем такого"
	КОНЕЦ КАК Поле1
ИЗ
	Справочник.Пользователи КАК Пользователи

А что делать, если, к примеру, нам надо получить название месяца в запросе? Писать огромную конструкцию в запросе некрасиво и долго, поэтому нас может выручить такая форма записи выше:

	ВЫБОР МЕСЯЦ(УС_РасчетПотребления_ГрафикОбороты.ПериодРасчета)
		КОГДА 1
			ТОГДА "Январь"
		КОГДА 2
			ТОГДА "Февраль"
		КОГДА 3
			ТОГДА "Март"
		КОГДА 4
			ТОГДА "Апрель"
		КОГДА 5
			ТОГДА "Май"
		КОГДА 6
			ТОГДА "Июнь"
		КОГДА 7
			ТОГДА "Июль"
		КОГДА 8
			ТОГДА "Август"
		КОГДА 9
			ТОГДА "Сентябрь"
		КОГДА 10
			ТОГДА "Октябрь"
		КОГДА 11
			ТОГДА "Ноябрь"
		КОГДА 12
			ТОГДА "Декабрь"
	КОНЕЦ КАК Месяц

Теперь конструкция выглядит не такой громоздкой и легко воспринимается.

14. Пакетное выполнение запроса.


Для того, чтобы не плодить запросы, можно создать один большой запрос, разбить его на пакеты и работать уже с ним.
Например, мне нужно получить из справочника "Пользователи" поля: "ДатаРождения" и доступные роли для каждого пользователя. в выгрузить это в разные табличные части на форме. Конечно можно сделать это в одном запросе, тогда придется перебирать записи или сворачивать, а можно так:

ВЫБРАТЬ
	Пользователи.Ссылка КАК ФИО,
	Пользователи.ДатаРождения,
	Пользователи.Роль
ПОМЕСТИТЬ втПользователи
ИЗ
	Справочник.Пользователи КАК Пользователи
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
	втПользователи.ФИО,
	втПользователи.ДатаРождения
ИЗ
	втПользователи КАК втПользователи
СГРУППИРОВАТЬ ПО
	втПользователи.ФИО,
	втПользователи.ДатаРождения
	
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
	втПользователи.ФИО,
	втПользователи.Роль
ИЗ
	втПользователи КАК втПользователи
СГРУППИРОВАТЬ ПО
	втПользователи.ФИО,
	втПользователи.ДатаРождения

тПакет = Запрос.ВыполнитьПакет();

ТП_ДатыРождения = тПакет[1].Выгрузить();
ТП_Роли = тПакет[2].Выгрузить();

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

15. Условия в пакетном запросе

Например, у нас есть пакетный запрос, где сначало мы получаем поля: "Наименование, ДатаРождения, Код" из справочника "Пользователи" и хотим из справочника "ФизЛица" получить записи с условием по этим полям.

 ВЫБРАТЬ
	Пользователи.ФизЛицо.Наименование КАК Наименование,
	Пользователи.ФизЛицо.ДатаРождения КАК ДатаРождения,
	Пользователи.ФизЛицо.Код КАК Код
ПОМЕСТИТЬ втПользователи
ИЗ
	Справочник.Пользователи КАК Пользователи
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
	ФизическиеЛица.Ссылка КАК ФизЛицо
ИЗ
	Справочник.ФизическиеЛица КАК ФизическиеЛица

Можно накложить условия таким образом:

ГДЕ
	ФизическиеЛица.Код В
			(ВЫБРАТЬ
				втПользователи.Код
			ИЗ
				втПользователи)
	И ФизическиеЛица.Наименование В
			(ВЫБРАТЬ
				втПользователи.Код
			ИЗ
				втПользователи)
	И ФизическиеЛица.ДатаРождения В
			(ВЫБРАТЬ
				втПользователи.ДатаРождения
			ИЗ
				втПользователи)

А Можно и так:

ГДЕ
	(ФизическиеЛица.Код, ФизическиеЛица.Наименование, ФизическиеЛица.ДатаРождения) В
			(ВЫБРАТЬ
				втПользователи.Код,
				втПользователи.Наименование,
				втПользователи.ДатаРождения
			ИЗ
				втПользователи)

Причем обязателено соблюдать порядок.

16. Вызов конструктора запросов для "условия" в пакетном запросе

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

 

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


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

Хотел рассмотреть использование индексов в запросах, но больно обширная тема. Вынесу в отдельную статью, либо позже добавлю здесь. 

upd1. Пункты 11,12
upd2. Пункты 13,14,15,16 

Используемая литература:
Язык запросов "1С:Предприятия 8" - Е.Ю. Хрусталева
Профессиональная разработка в системе 1С:Предприятие 8".

Запросы Язык запросов 1С Оптимизация

См. также

SALE! 15%

Инструментарий разработчика Роли и права Запросы СКД Программист Платформа 1С v8.3 Управляемые формы Запросы Система компоновки данных Конфигурации 1cv8 Платные (руб)

Набор инструментов программиста и специалиста 1С для всех конфигураций на управляемых формах. В состав входят инструменты: Консоль запросов, Консоль СКД, Консоль кода, Редактор объекта, Анализ прав доступа, Метаданные, Поиск ссылок, Сравнение объектов, Все функции, Подписки на события и др. Редактор запросов и кода с раскраской и контекстной подсказкой. Доработанный конструктор запросов тонкого клиента. Продукт хорошо оптимизирован и обладает самым широким функционалом среди всех инструментов, представленных на рынке.

10000 руб.

02.09.2020    159381    872    399    

861

Запросы Программист Бесплатно (free)

Увидел cheatsheet по SQL и захотелось нарисовать подобное, но про запросы.

18.10.2024    9868    sergey279    18    

64

Запросы Программист Платформа 1С v8.3 Запросы Конфигурации 1cv8 Бесплатно (free)

Столкнулся с интересной ситуацией, которую хотел бы разобрать, ввиду её неочевидности. Речь пойдёт про использование функции запроса АВТОНОМЕРЗАПИСИ() и проблемы, которые могут возникнуть.

11.10.2024    5163    XilDen    36    

80

Запросы Программист Запросы Бесплатно (free)

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

16.08.2024    7896    user1840182    5    

28

Математика и алгоритмы Запросы Программист Платформа 1С v8.3 Запросы Бесплатно (free)

Рассмотрим быстрый алгоритм поиска дублей с использованием hash функции по набору полей шапки и табличных частей.

08.07.2024    2393    ivanov660    9    

22

Запросы СКД Программист Стажер Система компоновки данных Россия Бесплатно (free)

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

15.05.2024    8684    implecs_team    6    

47

Запросы Программист Стажер Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

Часто поступают задачи по произвольному распределению общих сумм. После распределения иногда пропадают копейки. Суть решения добавить АвтоНомерЗаписи() в ВТ распределения, и далее используя функции МАКСИМУМ или МИНИМУМ можем положить разницу копеек в первую или последнюю строку знаменателя распределения.

11.04.2024    3391    andrey_sag    10    

36
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. ChiginAV 21.10.13 06:14 Сейчас в теме
Опечатка
"ВЫБРАТЬ Справочник.Банки.*" Выбирает все поля из справочника Товары
DrAku1a; Ekovichev; +2 Ответить
2. Ekovichev 825 21.10.13 06:41 Сейчас в теме
Спасибо. Исправил
DrAku1a; kild; +2 Ответить
3. ADirks 187 21.10.13 09:02 Сейчас в теме
Насчет подзапросов и временных таблиц я бы поосторожнее раздавал такие рекомендации.
Во первых, временные таблицы - это всегда зло, ибо лишняя нагрузка на сервер.
Во вторых, надо уточнить, о каких СУБД речь, потому что для MS SQL это абсолютно неверное утверждение. В лучшем случае, мы получим то же время выполнения. А в худшем - заметно больше, и попутно нагрузим сервер.
И ещё, не надо пытаться быть умнее оптимизатора - у него гораздо больше информации для принятия решения.
jobkostya1c_ERP; kild; IfYouWant_YouCan; +3 1 Ответить
15. Serj1C 483 21.10.13 12:22 Сейчас в теме
(3), (5) соединения с под запросами не оптимальны всегда.
Об этом пишут на http://kb.1c.ru/articleView.jsp?id=44
Говорят на тренинге 1С:Эксперт, спрашивают на экзамене.

По подзапросу нет статистики, а когда нет данных о таблице SQL выбирает способ соединения который ему проще всего - nested loops. В этом и проблема.
Риник; alur; dimon_upi; +3 Ответить
17. ADirks 187 21.10.13 12:53 Сейчас в теме
(15) В 1С вам ещё не то напишут, надо же иногда планы запросов самостоятельно курить.
И вообще, как можно верить людям, которые бацают кластерный индекс по GUID?!!
30. Gilev.Vyacheslav 1917 22.10.13 03:41 Сейчас в теме
(3) ADirks, Алексей, вы большой специалист по запросам? )))

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

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

Плюсы:
в отличии от вложенных запрос количество строк во временной таблице ПРОГНОЗИРУЕМОЕ, именно "ясность" с объемом выборки делает их удобными для оптимизации мест, которые выполняются неоправдано долго;
временные таблицы не пересекаются по блокировкам;
временные таблицы могут позволить не совершать повторные действия над одними и теме же данным в сложном запросе;
временные таблицы можно использовать для сбора промежуточных результатов из "подзапросов", таким образом это может упростить контроль RLS (т.е. проверке подвергать только итоговые данные, а не все промежуточные действия в сложном запросе).
kaaasteeen; Михаська; alur; Gendelf; aguriev; Alibek815; Aleskey_K; Shmell; Irwin; mickey.1cx; user811769; Kinestetik; Cерый; Serg O.; Flindex; jig; Nitralove; sstas007; theshadowco; exciter; jobkostya1c_ERP; karpik666; bird21; tormozit; krv2k; AllexSoft; teflon; Al-X; 1cprogr_nsk; echo77; zqzq; zarucheisky; dmpas; ShantinTD; spetzpozh; Serj1C; +36 Ответить
31. ADirks 187 22.10.13 06:55 Сейчас в теме
(30)
Сами по себе временные таблицы это просто инструмент, который надо применять понимая плюсы и минусы этой технологии.
Да, но методичка то от 1С как раз таки советует бездумно его применять.
Я может и небольшой специалист, но для оценки производительности пользуюсь специальными техническими средствами, а не голыми рекомендациями.
Риник; artbear; dmpas; +3 Ответить
4. KAPACEB.AA 466 21.10.13 09:44 Сейчас в теме
Спасибо за статью!

В п. 7 я бы все-таки уточнил, что левое соединение становится внутренним как следствие особенностей отработки условий ГДЕ, в которых одно из сравниваемых равно NULL - в таком случае условие возвращает NULL, что равносильно ЛОЖЬ. Имхо, в данном случае правильнее писать что-нибудь вроде "... ГДЕ ЕСТЬNULL(Оплата.Организация, Неопределено) = &Организация.
ekaterinaeon; PoZiTiFFF; +2 Ответить
5. Ekovichev 825 21.10.13 09:47 Сейчас в теме
Возможно вы правы,еще потестирую соединения с "тяжелыми" вложенными запросами на MySQL, посмотрим на разницу. Дело в том, что это не только мои рекомендации, так рекомендуют делать в метод. литературе 1С. И в типовых решениях я ни разу не видел соединений с вложенными запросами, хотя может и плохо смотрел. Спасибо за замечание, потестим получше
6. sommid 21.10.13 10:46 Сейчас в теме
по пункту 7 можно делать и так:
ВЫБРАТЬ
    Клиенты.Ссылка КАК Клиент,
    Оплата.Ссылка КАК Оплата
ИЗ
    Справочник.Клиенты КАК Клиенты
        ЛЕВОЕ СОЕДИНЕНИЕ Документ.Оплата КАК Оплата
        ПО Клиенты.Ссылка = Оплата.Клиент
           И Оплата.Организация = &Организация
8. Ekovichev 825 21.10.13 10:57 Сейчас в теме
(6) sommid, Пункт 7, про конструкцию "ГДЕ", у вас нет конструкции "ГДЕ" в запросе:)
10. sommid 21.10.13 11:09 Сейчас в теме
(8) ну да, может под имя раздела и не попал ). но отработает аналогично поставленной задаче
7. dagder 24 21.10.13 10:56 Сейчас в теме
Посмотрите ЗУП. Несколько уровней вложенности запросов с соединениями.
19. ShantinTD 91 21.10.13 15:43 Сейчас в теме
(7) dagder, и это хорошо разве? Попробуйте развернуть запрос из вложенных в пакетный, сравните время выполнения.

Правильно разложенный запрос позволяет убрать лишние повторные подзапросы, например.
У меня встречалась такая "оптимизация" после разложения в пакет: вместо 200 секунд запрос стал выполняться всего за 30. А последующая оптимизация сократила время выполнения еще вдвое! При сохранении результата, конечно!

Вот тут http://its.1c.ru/db/metod81#content:4050:1 написано следующее (для тех, у кого не откроется):

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

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

При написании запросов не следует использовать соединения с подзапросами. Следует соединять друг с другом только объекты метаданных или временные таблицы. Если запрос использует соединения с подзапросами, то его следует переписать с использованием временных таблиц.
...
Показать

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

А вот ПРЕДСТАВЛЕНИЕ() у меня (1С 8.3.4.304 и PostgreSQL 9.1.2-1.1С) дало неожиданно печальный результат: время выполнения запроса с 1`007`071 записью (выборка ссылок на элементы справочника из регистра сведений) выросло в 5 (задумайтесь только!) раз, против выборки непосредственно ссылок (49 секунд с представлениями против 9 секунд со ссылками).
Пример: (конфигурация - Розница. Магазин одежды и обуви 1.0) (помещение в ВТ - чтобы не тратить время на вывод 1000000 строк на экран)
ВЫБРАТЬ
	ЦеныНоменклатурыМагазинов.Номенклатура
ПОМЕСТИТЬ
	ВТ
ИЗ
	РегистрСведений.ЦеныНоменклатурыМагазинов КАК ЦеныНоменклатурыМагазинов

Выполняется за 9 секунд.
ЦеныНоменклатурыМагазинов.Номенклатура.Наименование
и
ПРЕДСТАВЛЕНИЕ(ЦеныНоменклатурыМагазинов.Номенклатура)
выполняются примерно за 49 секунд.

Так что вот вам информация к размышлению.
Риник; _OLEG; _7445_; Designer1C; +4 Ответить
26. ADirks 187 21.10.13 17:52 Сейчас в теме
(19)
А вот ПРЕДСТАВЛЕНИЕ() у меня (1С 8.3.4.304 и PostgreSQL 9.1.2-1.1С) дало неожиданно печальный результат: время выполнения запроса с 1`007`071 записью (выборка ссылок на элементы справочника из регистра сведений) выросло в 5 (задумайтесь только!) раз, против выборки непосредственно ссылок (49 секунд с представлениями против 9 секунд со ссылками).

Интересное кино... А можно ли как-то посмотреть, какой финальный запрос уходит на сервер? Неужто простой join с таблицей номенклатуры даёт такой эффект?
9. Yashazz 4790 21.10.13 11:05 Сейчас в теме
Это такая акция, что ли? Перепости общеизвестную чужую книжку на ИС и получи много плюсов и стартманей?
vynosmozga; Maxis; headMade; +3 1 Ответить
43. echo77 1906 23.10.13 08:30 Сейчас в теме
(9) Да! Вот мой пример: http://infostart.ru/public/118422/
Плюсов больше чем за все остальные мои публикации вместе взятые :-)
11. Трофимов_Николай 21.10.13 11:11 Сейчас в теме
Автору:Попробуйте перед размещением текста статьи проверять ее в WORD.Статья изобилует грамматическими ошибками:"комопновки","уопрядочивание" и т.д.
12. Ekovichev 825 21.10.13 11:51 Сейчас в теме
(11) nicol, Справедливое замечание, писал на ноуте, пальцы большие, кнопки маленькие:), но это не оправдывает, замечание учел, ошибки поправил.
13. p1l1gr1m 21.10.13 11:55 Сейчас в теме
Пункт 7 срочно исправьте.
"так как условие "ГДЕ" наложенное на правую таблицу, неявно превратило левое соединение во внутреннее" - это неправильное обоснование, новичков может ввести в заблуждение. В запросе из примера п. 7, в случае когда не произошло левого соединение таблицы Клиенты с таблицей Оплата, в конструкции ГДЕ производится сравнение null (это значение принимает в выборке поле Оплата.Организация, когда не произошло левое соединение с таблицей Клиенты) со значением из параметра "Организация", а булева операция проверки любого значения на равенство с null всегда вернет null, что в случае отбора по выборке интерпретируется СУБД как Ложь и соответственно поэтому не возвращаются строки выборки, где для строк из таблицы Оплата нет соотв. строк из таблицы Клиенты.
Поэтому лучше в п. 7 объяснить что такое троичная логика с null и каковы особенности ее реализации в современных СУБД.
sh1ne; NittenRenegade; teflon; spetzpozh; PoZiTiFFF; KAPACEB.AA; +6 Ответить
16. Ekovichev 825 21.10.13 12:25 Сейчас в теме
(13) p1l1gr1m, перефразировал в пункте 7 обоснование. Но ваше замечание:
"в конструкции ГДЕ производится сравнение null (это значение принимает в выборке поле Оплата.Организация, когда не произошло левое соединение с таблицей Клиенты)" Почему оно принимает значение NULL?Это справедливо, если не было вообще документа оплата для клиента. Например мы знаем, что оплаты для всех клиентов точно есть, но по разным организациям. Т.е. в таблице будут все клиенты и все оплаты, но когда на полученную таблицу наложится условие "ГДЕ", то в этом случае не будет сравнения Null с Null.
24. KAPACEB.AA 466 21.10.13 16:59 Сейчас в теме
(13) p1l1gr1m,
Поддерживаю! Собственно, об этом я и пытался сказать в своем комменте :)
28. Ekovichev 825 21.10.13 18:17 Сейчас в теме
(24) Mu_meson, Добавил пункт 12 в статью, немного про NULL, постарался объяснить как мог.
14. sa1m0nn 28 21.10.13 12:15 Сейчас в теме
Спасибо за статью.
ЗЫ: Освежите правила русского и поправьте в статье лишние мягкие знаки повально. "Все запросы, которые содержатЬся в статье"
Спасибо.
18. ShantinTD 91 21.10.13 15:36 Сейчас в теме
20. Ekovichev 825 21.10.13 16:13 Сейчас в теме
У меня нет такой здоровой таблицы под рукой, попробуйте так:

ВЫБРАТЬ
ЦеныНоменклатурыМагазинов.Номенклатура,
ПРЕДСТАВЛЕНИЕ(ЦеныНоменклатурыМагазинов.Номенклатура) КАК ПредставлениеНоменклатуры

ИЗ
РегистрСведений.ЦеныНоменклатурыМагазинов КАК ЦеныНоменклатурыМагазинов
21. ShantinTD 91 21.10.13 16:42 Сейчас в теме
(20) как и предположил глядя на предложенный запрос - время выполнения только увеличилось. До ~60 секунд. Объем выборки не изменился.

Тут читаем Встроенные функции языка запросов
Функция ПРЕДСТАВЛЕНИЕ
Описание:
Данная функция предназначена для получения строкового представления значения произвольного типа.
Параметр функции – выражение любого типа.
Возвращаемое значение – представление значения, тип Строка.
Результат работы функции не может быть использован внутри других функций, за исключением функции ПРЕДСТАВЛЕНИЕ.

Так что пользы пока что вижу например в этом:
ВЫБРАТЬ
    ПРЕДСТАВЛЕНИЕ(5)
, т.к.
ВЫБРАТЬ
    ВЫРАЗИТЬ(5 КАК СТРОКА(1))

вызовет ошибку.

У меня нет такой здоровой таблицы под рукой
. У меня 1000000 записей в тестовой базе (устаревшей). В живой базе - еще круче.
23. Ekovichev 825 21.10.13 16:47 Сейчас в теме
(21) ShantinTD, Завтра проверю, справочники есть, там миллионы записей, просто проверял на выборках в несколько тысяч, разницы во времени не заметил. Интересное наблюдение
22. Dzenn 894 21.10.13 16:46 Сейчас в теме
Ставлю плюс, но тема сисек запросов раскрыта не полностью. Где описание конструкции "ИМЕЮЩИЕ"?
25. Ekovichev 825 21.10.13 17:11 Сейчас в теме
(22) DZENN, Добавил в статью, 11 пункт.
27. ADirks 187 21.10.13 17:57 Сейчас в теме
(+26) ну и это, сравнивать то надо эквивалентные вещи, т.е. не
ВЫБРАТЬ
ЦеныНоменклатурыМагазинов.Номенклатура
ПОМЕСТИТЬ
ВТ
ИЗ
РегистрСведений.ЦеныНоменклатурыМагазинов КАК ЦеныНоменклатурыМагазинов

а

ВЫБРАТЬ
ЦеныНоменклатурыМагазинов.Номенклатура
ИЗ
РегистрСведений.ЦеныНоменклатурыМагазинов КАК ЦеныНоменклатурыМагазинов

т.к. одно дело на сервере одну табличку в другую перекачать, и совсем другое дело получить данные на клиенте.
29. ADirks 187 21.10.13 18:18 Сейчас в теме
Эксперимент на MS SQL

select
рег.Номенклатура
into #t1
from
регПартииНаличие рег

select
Н.Наименование
into #t2
from
регПартииНаличие рег
left join спрНоменклатура Н ON Н.ID = рег.Номенклатура

показал раскладку 31% / 69 % , т.е. время увеличилось примерно в 2 раза, что вполне ожидаемо
32. yuraos 1003 22.10.13 12:32 Сейчас в теме
Мддда!
Оччередной лииииикбез .... и восторги начинающих.
---
Хотел минусануть - да раздумал.
33. yuraos 1003 22.10.13 12:42 Сейчас в теме
(32)
---
Для демонстрации своей конструктивности предлагаю автору
(и думаю что коллеги знакомые с более развитыми SQL-языками меня поддержат)
указать следующие особенности языка запросов 1С:
34. yuraos 1003 22.10.13 12:49 Сейчас в теме
(33)
1) Функциональная ограниченность:
Очень небольшой список встроенных функций.

Хотя бы взять категорию строковых функций:
- нет функций отсекающие в строках пробелы (TRIM и ее разновидности);
- нет функции, возвращающей число символов в строке;
- нет функций, пребразующих число к его какому-нибудь строковому представлению
(а складывать строки с числами - нельзя!!!);
36. yuraos 1003 22.10.13 13:02 Сейчас в теме
(33)
2) Отсутствие поддержки коррелированных подзапросов:
В 1С в запросе нельзя использовать подзапросы, зависящие от значений полей основного запроса.

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

Нужный подзапрос цен может кроме номенклатуры и даты цены зависить еще и от типа цен и т.п.
---
Впринципе это ограничение обходится
...
НО ЦЕНОЙ АБСОЛЮТНОЙ ПОТЕРИ ЧИТАЕМОСТИ ТЕКСТА ЗАПРОСА!!!
37. yuraos 1003 22.10.13 13:06 Сейчас в теме
(33)
3) Ну а про возможность использования запросов для модификации данных
(хотя во временных таблицах) - можно даже и не мечтать!!!
39. SatanClaws 146 22.10.13 21:45 Сейчас в теме
(33) yuraos,
А экзист-то прикрутили, или воз и ныне там?
40. yuraos 1003 23.10.13 08:18 Сейчас в теме
(39) SatanClaws,
и ныне там ...
... специально ради проверки качнул платформу 8.3
---
как видно на скриншоте, из ключевых слов
ALL ANY SOME EXISTS IN TOP
в конструкторе запросов подсвечиваются только
ALL IN и TOP (ALL - используется по другому поводу - в объединениях запросов)
Прикрепленные файлы:
41. yuraos 1003 23.10.13 08:22 Сейчас в теме
(40)
впрочем это естественно.
раз нет коррелированных подзапросов -
- значит и нет смысла в использовании оператора EXISTS .
---
еще можно добавить что язык запросов 1С (как и встроенный)
не поддерживают блочных комментариев.
ShantinTD; +1 Ответить
57. SatanClaws 146 25.10.13 06:20 Сейчас в теме
(41)
Не, у меня как-то без коррелированных возникло желание.
Т.е. я на автомате, после 1ЦПП-шных прямых запросов, написал какую-то конструкцию с EXISTS - а восьмерка ее не съела.
Покурил маны - с удивлением обнаружил что его там не вообще.

Решить, конечно же, решил - но как-то через задницу (что-то в духе CASE WHEN (SELECT TOP 1 Поле FROM ...) IS NOT NULL THEN ...).
А вот моральная травма осталась на всю жЫзнь.

35. Ekovichev 825 22.10.13 12:55 Сейчас в теме
Хорошо, будет время опишу ограниченности языка запросов.
Но кстати число в строку можно превратить конструкцией ПРЕДСТАВЛЕНИЕ("Число"). Только конкатенация в запросе с таким полем невозможна.
38. zarucheisky 22.10.13 15:04 Сейчас в теме
//Добавлю немножко полезный (иногда) пример:
SELECT 1 A ,2 B INTO A UNION ALL
SELECT 3 A ,4 B UNION ALL
SELECT 5 A ,6 B UNION ALL
SELECT 7 A ,8 B;

SELECT 1 A ,2 B INTO B UNION ALL
//SELECT 2 A ,4 B UNION ALL
//SELECT 5 A ,6 B UNION ALL
SELECT 7 A ,8 B;

SELECT t_A.A,t_A.B FROM A t_A WHERE (t_A.A,t_A.B) NOT IN (SELECT t_B.A,t_B.B FROM B t_B)
// Здесь, что и интересно в условии фигурирует кортеж (t_A.A,t_A.B) и условие исключения из множества
// SELECT t_B.A,t_B.B FROM B t_B
42. yuraos 1003 23.10.13 08:25 Сейчас в теме
Блин!!!
Что-то Инфостарт после "линьки" глючит не по детски:
1. Подписка на комментарии не идет на почту (только спам от спекулянтов старт-манями).
2. Жму на "Просмотр" вводимого поста, а пост по простецки добавляется при этом на ветку.
AllexSoft; +1 Ответить
44. Ekovichev 825 23.10.13 08:33 Сейчас в теме
(42) yuraos, Тоже самое, упарило уже
45. echo77 1906 23.10.13 08:36 Сейчас в теме
(0)
2. Упорядочивание данных по ссылочному полю

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

Виртуальные таблицы , позволяют получить практически готовые данные для большинства прикладных задач.(СрезПервых,СрезПоследних,Остатки,Обороты,ОстаткиИОбороты) Ключевое слово здесь виртуальные. Эти таблицы не являются физическими, а компонуются системой налету, т.е. при получении данных из виртуальных таблиц система собирает данные из итоговых таблиц регистров, компонует, группирует и выдает пользователю.


Для регистров накопления и бухгалтерии виртуальные таблицы - это физические таблицы в БД.
На платформе 8.0-8.2 виртуальные таблицы периодических регистров сведений - это хранимые процедуры, т.е. действиетельно вирутальные таблицы. Нововведением на платформе 8.3 стало то что у периодических регистров сведений теперь будет еще и физическая таблица, которая хранит самые ранние записи(СрезПервых) и самые последние(СрезПоследних)

Поправьте меня, если где-то соврал
46. Ekovichev 825 23.10.13 08:52 Сейчас в теме
(45) echo77, Подкорректировал пункт про автоупорядочивание, тут вы правы. Про 8.3 и вирт. таблицы покурю еще:) Спасибо за констр. замечания
47. gaglo 23.10.13 10:22 Сейчас в теме
(45) и (46) - подозреваю, что подкорректировали и перегнули в другую сторону. ИМХО - АВТОУПОРЯДОЧИВАНИЕ способно серьезно замедлить запрос только в сочетании с отсутствием фразы УПОРЯДОЧИТЬ ПО. Туманное же указание на "некоторые" (неописанные) "случаи" практически ничего не дает.
48. nikolal 23.10.13 10:44 Сейчас в теме
49. Ekovichev 825 23.10.13 11:29 Сейчас в теме
(48) nikolal, Интересное решение, можно сделать и так. Добавлю в статью.Спасибо.
50. chmv 23.10.13 12:08 Сейчас в теме
51. kraynev-navi 681 23.10.13 12:13 Сейчас в теме
Спасибо. Очень доступно.
Кое-где в запросах тег br проскочил

------------
ГДЕ< br > Клиенты.Ссылка В (&Клиенты)
------------
52. DAnry 9 23.10.13 13:03 Сейчас в теме
Вообще то все это известно, ничего нового. Но для новичков полезно...
58. VasilevaHelen 127 25.10.13 13:38 Сейчас в теме
Согласна с(52), ставлю "+".
53. Dementor 1035 23.10.13 14:20 Сейчас в теме
В свете пункта 12. Значение NULL не будет лишним отметить, что все поля через точку в запросе для пустых ссылок содержат значение NULL. Об этом часто забывают и считают, что платформа по аналогии с объектной моделью будет ставить значения по-умолчанию для нужных типов.

P.S. что-то тут на инфостарте нахимичили и без авиков комментарии теперь не добавить...
54. anchovy 24 23.10.13 16:24 Сейчас в теме
>>Только в первом запросе записей будет меньше так, как записи , например с одинаковой номенклатурой, свернутся.
Разные запросы дают разные результаты. Удивительно.
55. bulpi 217 23.10.13 16:46 Сейчас в теме
В п.12 вместо
Справочник.КПК_Пайщики КАК КПК_Пайщики
нужно
Справочник.Клиенты КАК Клиенты

И еще подобные ошибки. Вообще, 12 пункт автор, видимо, писал второпях. Нужно вычитать.
56. AlexeyFreeLife 25.10.13 05:52 Сейчас в теме
Зачем дублировать азы, написанные в десятках статей, книгах и даваемых на курсах?
59. BAPBAP 27.10.13 15:40 Сейчас в теме
Относительно запросов в цикле. Если избежать цикла никак не удается, то результат лучше поместить во временную таблицу, и уже в цикле выполнять запросы именно к временной таблице.
60. chmv 28.10.13 08:43 Сейчас в теме
61. ShantinTD 91 28.10.13 09:52 Сейчас в теме
И опять...
Идем по ссылке http://its.1c.ru/db/metod81#content:2655:1 и читаем следующее
Поле Представление

Каждая объектная таблица в информационной базе имеет виртуальное поле - "Представление". Это поле содержит текстовое представление объекта. В запросе возможно получать данное поле точно также как и другие поля таблиц, однако никакие операции с данным полем выполнять нельзя. Данная особенность связана с тем, что это поле является виртуальным, и, на самом деле, при получении данного поля из базы данных, запрос получает несколько полей, а при получении значения поля из результата запроса преобразовывает полученные значения в строку. Таким образом, единственное, что можно сделать с полем "Представление", это получить его в результат запроса.

Как следствие, результат запроса не рекомендуется упорядочивать по полю "Представление", т.к. это не приведет к желаемому результату - результат запроса будет упорядочен в порядке возрастания ссылок объектов. Подробнее об этом можно прочитать в разделе "Особенности упорядочивания по ссылочным полям".
Функция Представление()

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

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

Применение функции Представление() также может быть полезным при получении представления поля - перечисления, в случае исполнения запроса через COM-соединение.


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

И еще: Представление заложено, видимо, очень давно, но возможность использовать его появилась только с версии 8.3 (в режиме совместимости 8.2.16 - еще нельзя). И для этого нужно прописать обработчик
ОбработкаПолученияПредставления()
и
ОбработкаПолученияПолейПредставления()
в модуле менеджера объекта. До тех пор, пока обработчики не прописаны - используется стандартное представление "в виде кода" или "в виде наименования".

Специально провел замеры не только времени выполнения запроса, но и его обработки: результат опять же далеко не в пользу функции ПРЕДСТАВЛЕНИЕ().

Резюме: использование функции ПРЕДСТАВЛЕНИЕ() дало предсказуемый, но крайне неприятный результат. На мой взгляд замедление вполне закономерно, но неоправданно велико. Использование ПРЕДСТАВЛЕНИЕ() оправдано только в тех случаях, когда представление действительно должно отличаться от стандартного, и это отличие оформлено (то есть прописаны обработчики).
62. mr.Kot 29.10.13 15:03 Сейчас в теме
Полезная статья, знание запросов - первое, что проверяют на собеседованиях, т.к. в запросы обычно долго "вкуривают".
63. el7 31.10.13 14:11 Сейчас в теме
запросы вещь отличная, и очень-очень полезная)))
64. DrAku1a 1745 07.11.13 03:11 Сейчас в теме
ИМХО: Статья из разряда "Золотые страницы Инфостарта".
Такие знания и применение их на практике - это одна из деталей, которая делает из программиста настоящего профессионала!
65. zarucheisky 07.11.13 11:01 Сейчас в теме
Сколько уже писано/переписано тем про запросы на той же мисте.

ИМХО, при написании запросов важно понимать ЧТО, ОТКУДА и КАК выбрать надо.
Избегать многоточий в выражениях языка запросов.
Ну и для начала лучше всего проштудировать что-то типа Ицик Бен-Ган Основы t-SQL для общего развития.
dimon_upi; AllexSoft; +2 Ответить
66. ZLENKO 398 14.01.14 18:08 Сейчас в теме
Почитал комментарии - любят 1С-неги измерять размеры... :-)
67. Rik30 14 25.02.14 08:25 Сейчас в теме
а как в запросе выбрать все справочники? Допустим нужно в запросе узнать кол-во записей всех справочников БД.
68. Ekovichev 825 25.02.14 08:43 Сейчас в теме
Если используя только запрос, то необходимо выбрать все справочники. и конструкцией:
КОЛИЧЕСТВО(Различные(<Справочник1>.Ссылка) КАК КоличествоЗаписей
ОБЪЕДИТЬ ВСЕ
КОЛИЧЕСТВО(Различные(<Справочник2>.Ссылка) КАК КоличествоЗаписей
....
Потом просуммировать.

Или программно:

Для Каждого Справочник Из Метаданные.Справочники Цикл
Запрос=Новый Запрос;
Запрос.Текст=
"ВЫБРАТЬ
| КОЛИЧЕСТВО(*) КАК Кол
|ИЗ
| Справочник."+Справочник.Имя;

КоличествоЗаписей = КоличествоЗаписей + Запрос.Выполнить().Выгрузить().Итог("Кол");

КонецЦикла;
Как-то так...
69. bashirov.rs 31 30.10.14 12:47 Сейчас в теме
Не плохая статейка. Спасибо!
70. ZloyProger 8 19.12.14 10:13 Сейчас в теме
Доброго времени суток, коллеги! Замечание по пункту 13 (короткая форма записа оператора ВЫБОР..) - кто-нибудь проверял на не примитивные (блин как-то по-русски не могу сформулировать..) условия, т.е. типа:
ВЫБОР ЕПСБУОборотыДтКт.Регистратор ССЫЛКА
КОГДА Документ.ОтражениеЗарплатыВУчете Тогда "Отражение ЗП"
ну и т.д. Пробовал всяко и в скобках и без и такой вариант тоже
ВЫБОР ЕПСБУОборотыДтКт.Регистратор
КОГДА ССЫЛКА Документ.ОтражениеЗарплатыВУчете Тогда "Отражение ЗП"
выдает ошибки.. Нужно для следующей задачи - "нормально" упорядочить результат запроса по виду документа и сумме.
ЗЫ. АВТОУПОРЯДОЧИВАНИЕ, ПРЕДСТАВЛЕНИЕ() и .Представление соответственно не помогают приходится писать зверскую неудобочитаемую конструкцию на каждый возможный документ регистратор((
71. soulsteps 73 19.12.14 15:12 Сейчас в теме
ZloyProger, попробуй так

ВЫБОР ТИПЗНАЧЕНИЯ(ЕПСБУОборотыДтКт.Регистратор)
КОГДА Документ.ОтражениеЗарплатыВУчете Тогда "Отражение ЗП"
КОГДА Документ.<НеобходимыйТип> Тогда "НеобходимыйТип"
...
КОНЕЦ

Недавно писал отчет, использовал такую же конструкцию - все прекрасно отрабатывает.
akR00b; Windsor77; +2 Ответить
72. jaroslav.h 180 11.02.15 23:57 Сейчас в теме
Ой, за "16. Вызов конструктора запросов для "условия" в пакетном запросе" это трюк я вам так благодарный )
73. Ekovichev 825 12.02.15 06:38 Сейчас в теме
74. markovki 20 02.04.15 15:55 Сейчас в теме
Спасибо!
Автору 5+ за статью.
Ставлю ПЛЮС
75. mtv:) 1028 26.04.15 22:44 Сейчас в теме
Спасибо за статью! Углядел для себя несколько полезных фишек.

Есть замечание:
Совет "10. Запросы в цикле" думаю, что бесполезный.
Ваше утверждение: "Это избавит систему от синтаксической проверки запроса в цикле." - это миф.
Синтаксическая проверка запроса происходит при исполнении метода Запрос.Выполнить(), а это происходит как раз в теле цикла. И из цикла это ни как не выкинешь.
Так что от "вынесения создания запроса за пределы цикла" прироста производительности ожидать не следует.
76. AlexiyI 27.04.15 14:16 Сейчас в теме
Статья из разряда "то что надо", спасибо большое!
Кстати, по поводу п. 15.: эти два запроса могут и не возвращать идентичную информацию, думаю, стоило заострить на это внимание. Т.е. во втором случае результат будет как при соединении двух таблиц, т.е. строки и поля таблиц сравниваются не каждый с каждым, а поля строки первой таблицы сравниваются с полями только одной строки второй таблицы.
77. Ekovichev 825 28.04.15 13:11 Сейчас в теме
(76) AlexiyI,
Спасибо.
Да, вы правы по 15 пункту, внесу изменения.
78. dimon_upi 16.06.15 15:58 Сейчас в теме
Автор молодец, собрал знания в одном месте. Возможно имеет смысл написать продолжение по дзену запросов 1С и их оптимизации, если еще не написал.

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

пункт 5 - от примера с left join и where сначала впал в недоумение, потом дочитал и понял что это из разряда - как не надо делать ) Надо до кучи еще full join пример привести. А то по началу некоторые парятся что нужно по isnull связывать в where.

пункт 13 - вроде обычный "Case", никогда не думал что она недокументирована +)

Для улучшения навыков в запросах 1С стоит пописать запросы на SQL, познакомится с вьюхами, триггерами, процедурами (функции ф топку). Потыкать профайлер, покурить статистику... Офигеть от того что порой план для запроса в транзакции и без отличается координально.

Жалко что нет coalesce, exists, set statistics profile ON, хинтов, процедур и еще много-много чего из стандарта SQL :((((
79. kmanas 25.09.15 22:50 Сейчас в теме
Здравствуйте, несколько дней уже изучаю запросы, решил попрактиковаться в консоле запросов, и тут же возник вопрос, возможно ли исключить пустые строки из запроса? Код моего первого запроса прост до безобразия:

ВЫБРАТЬ Первые 15
Производитель
ИЗ
Справочник.Номенклатура

Отобразились строки, и заполненные и пустые. Попытка писать условия добавив секцию ГДЕ не помогло. Искал в инете, но ничего толком об этом нет, косвенно есть инфа, что в самом запросе этого не сделать.
80. Ekovichev 825 27.09.15 06:16 Сейчас в теме
Если я вас правильно понял, что вам нужны строки с заполненным производителем. Тогда, если производитель ссылочный ти, то будет так:

ВЫБРАТЬ Первые 15
Производитель
ИЗ
Справочник.Номенклатура
ГДЕ
НЕ Производитель.Ссылка ЕСТЬ NULL
81. kmanas 07.10.15 17:33 Сейчас в теме
Да, ссылочные. Выходит в моем случае в ГДЕ к полю надо добавлять <.Ссылка>. Спасибо, работает!
82. 1c.pro.fun 188 05.11.15 13:01 Сейчас в теме
По поводу конструкции ПРЕДСТАВЛЕНИЕ. Если используется пакетный запрос и платформа автоматически добавляет представление при выборе поля в первом пакете, а затем это поле используется во втором и при выборе поля, платформа также добавляет представление. Явно оба представления оставлять нет смысла. Вопрос: какое из двух представлений нужно оставить? Любое? Или только в первом пакете, так как в нем происходит первоначальное обращение к данным? Как будет быстрее?
83. marinelle 16.11.15 16:37 Сейчас в теме
Добрый вечер. Имеется таблица дат, нужно присоединить квартальные обороты до даты выпуска в разрезе номенклатуры. Кто подскажет, как это сделать???
84. sergik_nsk 148 28.03.16 10:01 Сейчас в теме
не плохая статья чтобы освежить мозги
85. mgn 13.01.17 07:08 Сейчас в теме
ну вот влез в древнюю тему, просто хочется реабилитировать 1C в отношении exists
все наверное забыли про

Реализация группового оператора вхождения

В отличие от простого оператора вхождения, аналог которого имеется в большинстве СУБД (оператор IN языка SQL), групповой оператор вхождения не имеет точных аналогов в SQL. Поэтому при использовании группового оператора вхождения важно учитывать механизм его перевода в SQL. Оператор вида:

Копировать в буфер обмена
(<Выражение 1>, ..., <Выражение N>) В (
    ВЫБРАТЬ <Колонка 1>, ..., <Колонка N>
    ИЗ <Источники>
    ГДЕ <Условие>
)
при выполнении его на СУБД будет иметь вид:

Копировать в буфер обмена
EXISTS(
    SELECT 1
    FROM <Источники>
    WHERE (<Условие>) AND <Выражение 1> = <Колонка 1> AND ... AND <Выражение N> = <Колонка N>
)
Если вложенный запрос содержит агрегатные функции и/или раздел СГРУППИРОВАТЬ ПО, то групповой оператор вхождения вида:

Копировать в буфер обмена
(<Выражение 1>, ..., <Выражение N>) В (
    ВЫБРАТЬ <Колонка 1>, ..., <Колонка N>
    ИЗ <Источники>
    ГДЕ <Условие 1>
    СГРУППИРОВАТЬ ПО <Список группировки>
    ИМЕЮЩИЕ <Условие 2>
)
на языке SQL будет записан так:

Копировать в буфер обмена
EXISTS(
    SELECT 1
    FROM <Источники>
    WHERE <Условие 1>
    GROUP BY <Список группировки>
    HAVING (<Условие 2>) AND <Выражение 1> = <Колонка 1> AND ... AND <Выражение N> = <Колонка N>
)

Показать
kitsey; dimon_upi; KAPACEB.AA; +3 Ответить
86. dimon_upi 13.01.17 11:19 Сейчас в теме
(85)
exists просто привычней ;-)
плюс он все же на мой взгляд более универсален. Хотя вы правы групповой оператор вхождения покрывает большинство простых конструкций, и при этом любую более сложную конструкцию можно свести к простым и будет хоршо. НО глаз то привык к экзисту.
87. user668780_xeslifex 18.01.17 02:08 Сейчас в теме
Спасибо за информацию, пригодилось)
88. igor_gk 49 13.03.17 10:57 Сейчас в теме
Короче, в 1С уже как в механике пошло разделение на теормех и реальную работу механиков на производстве... Спасибо. Пишите побольше таких статей. Хороший уклон в простоту, понятность и практичность изложения.
89. marivgo 23.05.17 16:50 Сейчас в теме
Разве Автоупорядочивание по ссылке документа - это сортировка по сочетанию Дата и Номер, а не по моменту времени? В СКД задала в настройках сортировку строк отчета по Регистратору - предполагаю, что это аналог автоупорядочивания. Все документы выстроились действительно в порядке Дата-Номер. Но после того, как я в первом из документов вручную исправила Номер на больший (у всех остальных с той же датой были меньшие номера) , положение данного документа не изменилась. Отсюда делаю вывод, что все-таки непосредственно Номер документа в автоупорядочивании не участвует, скорее его ссылка.
90. borodaty_pontorez 23.05.17 17:01 Сейчас в теме
В целом довольно таки познавательно, но мне кажется если я покажу это нашем новичку, он выпучит глаза. Надо плавно подвести к этой информации о запросах. Спасибо за труд!
91. Glebis 13 25.05.18 16:24 Сейчас в теме
По пункту 10. Запросы в цикле.

Если мне нужно делать запросы в цикле, то я делаю сначала общий "покрывающий" запрос, присоединяю менеджер ВТ, затем задаю текст запроса каждой итерации, к которой также присоединяю менеджер ВТ, и уже в каждой итерации меняя параметры итерационного запроса делаю "запрос в цикле" к менеджеру ВТ, что никак не нагружает оборудование, кроме TempDB.
92. Sherkhan 17.06.18 08:10 Сейчас в теме
8.2 ругается на отсутствия метола "Пустой()" из п.10.
93. Sevt_RND 27.10.18 13:23 Сейчас в теме
По п.10 правильней передать всю таблицу клиентов в запрос, а не гонять цикл.
94. Sergey_1c 54 23.07.19 11:27 Сейчас в теме
В пункте 15, по-моему, ошибка. Условия отбора получаются разные. В первом случае идет проверка на вхождение в массив каждого проверяемого поля, а во втором идет построчное сравнение таблиц по трем полям одновременно.
95. nicxxx 255 03.07.22 14:28 Сейчас в теме
Некропост, но не могу пройти мимо:)
Сорри, если уже писали про это, все комменты не читал.

Типичная ошибка человека, следующего рекомендациям фирмы 1С:

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

Объяснение, почему данное утверждение неверно, дается в моей статье:
https://infostart.ru/1c/articles/880836/
Оставьте свое сообщение