1с ВЫРАЗИТЬ в запросе
Многие программисты 1с, особенно молодые специалисты, часто недооценивают использование в 1с запросах оператора ‘ВЫРАЗИТЬ’ (функции языка запросов). Большинство использует его исключительно для преобразования значений в примитивный тип данных (строка, число, булево):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
//... | ВЫРАЗИТЬ(Товары.Цена * Товары.Количество КАК ЧИСЛО(15, 2)) КАК Сумма, //... | ВЫРАЗИТЬ(ВариантыОтчетов.Автор.Наименование КАК СТРОКА(1000)) КАК АвторПредставление, //... |ГДЕ ВЫРАЗИТЬ(НЕ ВнешниеПользователи.Ссылка ЕСТЬ NULL КАК БУЛЕВО) //... | ДанныеДляСопоставленияПоНаименованию КАК ДанныеДляСопоставленияПоНаименованию | ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник._ДемоНоменклатура КАК _ДемоНоменклатура | ПО (_ДемоНоменклатура.Наименование = (ВЫРАЗИТЬ(ДанныеДляСопоставленияПоНаименованию.Номенклатура КАК СТРОКА(500)))) //... | ДОБАВИТЬКДАТЕ(ДАТАВРЕМЯ(2015,1,1),СЕКУНДА, ВЫРАЗИТЬ((РАЗНОСТЬДАТ(ДАТАВРЕМЯ(2015,1,1), ЗамерыКомментарииСтатистики.Период, СЕКУНДА) + 63555667200)/&ПериодАгрегации - 0.5 КАК ЧИСЛО(11,0)) * &ПериодАгрегации - 63555667200) КАК Период, | ДОБАВИТЬКДАТЕ(ДАТАВРЕМЯ(2015,1,1),СЕКУНДА, ВЫРАЗИТЬ((РАЗНОСТЬДАТ(ДАТАВРЕМЯ(2015,1,1), ЗамерыКомментарииСтатистики.Период, СЕКУНДА) + 63555667200)/&ПериодАгрегации - 0.5 КАК ЧИСЛО(11,0)) * &ПериодАгрегации - 63555667200 + &ПериодАгрегации - 1) КАК ПериодОкончание, | ДОБАВИТЬКДАТЕ(ДАТАВРЕМЯ(2015,1,1),СЕКУНДА, ВЫРАЗИТЬ((РАЗНОСТЬДАТ(ДАТАВРЕМЯ(2015,1,1), ЗамерыКомментарииСтатистики.Период, СЕКУНДА) + 63555667200)/&ПериодУдаления - 0.5 КАК ЧИСЛО(11,0)) * &ПериодУдаления - 63555667200) КАК ИдентификаторУдаления, |
К примеру мы хотим получить количество документов с одинаковым комментарием. Для этого мы хотим сгруппировать документы по реквизиты ‘Комментарий’ и получить количество ссылок для каждого их них. Но поскольку реквизит ‘Комментарий’ имеет тип ‘строка / неограниченная длина’, то группировку мы использовать не можем. Но мы можем преобразовать это реквизит к строке ограниченной длины (к примеру 100) и затем уже сгруппировать наши данные:
1 2 3 4 5 6 7 8 |
ТекстЗапроса = "ВЫБРАТЬ | КОЛИЧЕСТВО(_ДемоПоступлениеТоваров.Ссылка) КАК Ссылка, | ВЫРАЗИТЬ(_ДемоПоступлениеТоваров.Комментарий КАК СТРОКА(100)) КАК Комментарий |ИЗ | Документ._ДемоПоступлениеТоваров КАК _ДемоПоступлениеТоваров | |СГРУППИРОВАТЬ ПО | ВЫРАЗИТЬ(_ДемоПоступлениеТоваров.Комментарий КАК СТРОКА(100))" |
Аналогично будет работать и для соединения таблиц по реквизиту с типом строка неограниченной длины (так как запросах нельзя сравнивать поля неограниченной длины и поля несовместимых типов):
1 2 3 4 5 6 7 8 9 10 |
ТекстЗапроса = "ВЫБРАТЬ | КОЛИЧЕСТВО(_ДемоПоступлениеТоваров.Ссылка) КАК Ссылка, | ВЫРАЗИТЬ(_ДемоПоступлениеТоваров.Комментарий КАК СТРОКА(100)) КАК Комментарий |ИЗ | Документ._ДемоПоступлениеТоваров КАК _ДемоПоступлениеТоваров | ЛЕВОЕ СОЕДИНЕНИЕ Документ._ДемоЗаказПокупателя КАК _ДемоЗаказПокупателя | ПО ((ВЫРАЗИТЬ(_ДемоПоступлениеТоваров.Комментарий КАК СТРОКА(50))) = (ВЫРАЗИТЬ(_ДемоЗаказПокупателя.Комментарий КАК СТРОКА(50)))) | |СГРУППИРОВАТЬ ПО | ВЫРАЗИТЬ(_ДемоПоступлениеТоваров.Комментарий КАК СТРОКА(100))" |
1 2 3 4 5 6 7 8 9 |
|//////////////////////////////////////////////////////////////////////////////// |ВЫБРАТЬ | МАКСИМУМ(_ДемоНоменклатура.Ссылка) КАК Ссылка, | ДанныеДляСопоставленияПоНаименованию.Идентификатор КАК Идентификатор, | КОЛИЧЕСТВО(ДанныеДляСопоставленияПоНаименованию.Идентификатор) КАК Количество |ИЗ | ДанныеДляСопоставленияПоНаименованию КАК ДанныеДляСопоставленияПоНаименованию | ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник._ДемоНоменклатура КАК _ДемоНоменклатура | ПО (_ДемоНоменклатура.Наименование = (ВЫРАЗИТЬ(ДанныеДляСопоставленияПоНаименованию.Номенклатура КАК СТРОКА(500)))) |
На этом в принципе и заканчивают использование всех возможностей оператора ‘ВЫРАЗИТЬ’, а зря! Есть более интересный момент: преобразование составного типа данных к одиночному!
Рассмотрим пример с применением SQL Profiler для отладки запросов в 1С. О том как его настроить читайте по ссылке. Допустим у нас есть регистр накопления ‘бит_ДвиженияДенежныхСредств’ и регистратор у него составного типа (4 различных документа – 4 таблицы):
И у нас есть задача: необходимо получить номера всех документов ‘ПоступлениеНаРасчетныйСчет’ (из этого регистра) с определенной даты. 95 процентов сделают так:
В принципе поставленную задачу они решат. Но если мы посмотрим план выполнения запроса (как это сделать читай здесь):
То увидим что у нас выполнилось 4 левых соединения – ровно столько, сколько возможно типов регистраторов. Было бы 25 типов – соответственно получили бы 25 левых соединений. Но они то нам по факту не нужны (лишняя нагрузка), так как мы хотим отобрать данные только из одной таблицы! Поэтому в данном запросе мы используем оператор ‘ВЫРАЗИТЬ’ и преобразуем наш регистратор к нужному нам типу:
И в плане запроса мы видим уже только 1 необходимое соединение:
Вот на таком примере мы с вами попробовали разобраться как максимально выгодно использовать оператор ‘Выразить’ в запросе. Похожий пример можете посмотреть на сайте 1с. В своей типовой конфигурации или в библиотеке стандартных подсистем вы можете найти массу примеров в коде с использованием данного оператора! В общем учитесь и всегда узнавайте что-то новое!
Всем удачи! Пока!
Очень доходчиво. Спасибо!