Как получить последний документ в запросе 1с
Наверняка многие коллеги сталкивались с такой задачей, как получение первых/последних документов в выборке. В зависимости от необходимого результата к реализации решения можно подойти различными способами.
Разберем на примере демо-базы УТ11, найдем последние документы прихода номенклатуры по регистру «ТоварыНаСкладе». Под последним документом в контексте данной задачи может пониматься как документ с наибольшей датой документа, так и последний документ, введенный пользователем.
В ниже приведенных пакетных запросах первый запрос пакета нужен для демонстрации картины в целом, последующие запросы формируют результат.
Для одной номенклатуры все просто, нужно сделать упорядочивание по регистратору и выбрать первый документ.
Без автоупорядочивания сортировка произойдет без учета даты документа, по уникальному идентификатору. В этом случае, документы введенные позже приходного ордера ЦУ-33 задним числом встанут в начало выборки. Уберем «АВТОУПОРЯДОЧИВАНИЕ» из запроса и посмотрим результат.
Если воспользоваться методом получения даты создания объекта из GUID, то в первом случае 3339428b-6656-11e0-af2a-0015e9b8c48d создан 14.04.2011, во втором b2c7cfa2-6ca9-11e0-af30-0015e9b8c48d — 22.04.2011. То есть второй способ можно применять, если нужно определить последний документ прихода, введенный пользователем.
В случае, когда нужно определить последние документы для перечня номенклатуры конструкция «ВЫБРАТЬ ПЕРВЫЕ» нам уже не подходит. Поэтому, чтобы свернуть выборку по регистратору, будем использовать функцию МАКСИМУМ.
Как видно из результата, функция МАКСИМУМ сворачивает выборку по GUID объекта. То есть, этот способ не подходит для случая, когда нам нужно получить последний документ, исходя из даты документа. Получать перечень номенклатуры и потом в цикле для каждой позиции получать последний документ тоже не наш вариант, замедляется быстродействие. Поэтому перепишем запрос, добавим временную таблицу, в которой свернем выборку по максимуму даты регистратора. Эту дату и будем использовать для соединения с основной выборкой. В последнем запросе так же сворачиваем выборку по максимуму регистратора, но теперь мы получим последний введенный документ с учетом последней даты документа.
UPD: как правильно заметили в комментариях, механизм генерации ГУИД обеспечивает только уникальность, но не возрастающую последовательность. На момент написания статьи проведенные тесты давали необходимый результат. Но гарантии, что выявленная закономерность сохранится в последующих версиях платформы, нет. Поэтому, если необходимо фиксировать момент создания документов, то лучше реализовать свой механизм. Например, с использованием регистра сведений.
12 комментариев:
В последнем запросе таблицы соединяются по дате, так делать нельзя т.к. это будет не правильно работать в случае когда у разных поступлений одинаковая дата и время.
Почему нет? В последнем запросе в случае, когда встретится два и более документа с одинаковым датой/временем, возьмется только один по МАКСИМУМ(ТоварыНаСкладахОбороты.Регистратор), иначе говоря последний введенный документ поступления на эту дату/время.
Получается МАКСИМУМ() выбирает максимальный уникальный идентификатор, который икрементально строится на основании даты создания ссылки ?
В общих чертах, да. По результатам, МАКСИМУМ по ссылке дает ссылку (он же УИД) на последний введенный объект.
Этот комментарий был удален автором.
Михаил Андрияшкин, объекты зачастую мигрируют из одних баз в другие и выгружаются по ссылке, поэтому "МАКСИМУМ по ссылке дает ссылку" не верно.
Согласен! Вчера нужно было отобрать в запросе максимальный документ по дате. В результате пришлось отбирать документы по максимальной дате, а потом по максимальной ссылке. При этом все равно отобрался не последний документ, т.к. документы были созданы загрузкой. И тут уж ничего не поделать.
Этот комментарий был удален автором.
Спасибо, полдня мучался пока не нашел этот пост. Вот что получилось у меня под мою задачу
ВЫБРАТЬ
ТоварыОрганизацийОбороты.Организация КАК Организация,
ТоварыОрганизацийОбороты.АналитикаУчетаНоменклатуры.Склад КАК Склад,
ТоварыОрганизацийОбороты.АналитикаУчетаНоменклатуры.Номенклатура КАК Номенклатура,
ТоварыОрганизацийОбороты.АналитикаУчетаНоменклатуры.Характеристика КАК Характеристика,
МАКСИМУМ(ТоварыОрганизацийОбороты.Регистратор.Дата) КАК ДатаПоступления
ПОМЕСТИТЬ ВТ_ДатыПоступлений
ИЗ
РегистрНакопления.ТоварыОрганизаций.Обороты(, &КонецПериода, Регистратор, АналитикаУчетаНоменклатуры.Склад В ИЕРАРХИИ (&ГруппаСкладов)) КАК ТоварыОрганизацийОбороты
ГДЕ
ТоварыОрганизацийОбороты.Регистратор ССЫЛКА Документ.ПриобретениеТоваровУслуг
СГРУППИРОВАТЬ ПО
ТоварыОрганизацийОбороты.Организация,
ТоварыОрганизацийОбороты.АналитикаУчетаНоменклатуры.Склад,
ТоварыОрганизацийОбороты.АналитикаУчетаНоменклатуры.Номенклатура,
ТоварыОрганизацийОбороты.АналитикаУчетаНоменклатуры.Характеристика
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
ВТ_ДатыПоступлений.Организация КАК Организация,
ВТ_ДатыПоступлений.Склад КАК Склад,
ВТ_ДатыПоступлений.Номенклатура КАК Номенклатура,
ВТ_ДатыПоступлений.Характеристика КАК Характеристика,
ВТ_ДатыПоступлений.ДатаПоступления КАК ДатаПоступления,
МАКСИМУМ(ТоварыОрганизацийОбороты.Регистратор) КАК Поступление
ИЗ
ВТ_ДатыПоступлений КАК ВТ_ДатыПоступлений
ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыОрганизаций.Обороты(, &КонецПериода, Регистратор, АналитикаУчетаНоменклатуры.Склад В ИЕРАРХИИ (&ГруппаСкладов)) КАК ТоварыОрганизацийОбороты
ПО ВТ_ДатыПоступлений.ДатаПоступления = ТоварыОрганизацийОбороты.Регистратор.Дата
ГДЕ
ТоварыОрганизацийОбороты.Регистратор ССЫЛКА Документ.ПриобретениеТоваровУслуг
СГРУППИРОВАТЬ ПО
ВТ_ДатыПоступлений.Организация,
ВТ_ДатыПоступлений.Склад,
ВТ_ДатыПоступлений.Номенклатура,
ВТ_ДатыПоступлений.Характеристика,
ВТ_ДатыПоступлений.ДатаПоступления
УПОРЯДОЧИТЬ ПО
Организация,
Склад,
Номенклатура,
Характеристика,
ДатаПоступления УБЫВ,
Поступление УБЫВ
Но вот в чем меня терзают смутные сомнения в собственной профпригодности. Как поведет себя этот запрос при большом количестве накопленных данных, не будет ли выполняться по полчаса. В принципе можно исходя из конкретных условий ограничить дату начала выбирания оборотов, но тогда получается некошерно, не все последние поступления будут выбираться.
Запрос явно не оптимален. Выборка из оборотного регистра с периодичностью по регистратору будет всегда читать данные из таблицы движений. В вашем случае все движения регистра по дату окончания. Так же есть связь по полю от составного типа (ПО ВТ_ДатыПоступлений.ДатаПоступления = ТоварыОрганизацийОбороты.Регистратор.Дата) и прочие неоптимальности. Я рекомендую разработать отдельный регистр с подходящей структурой метаданных для ваших целей. Навскиду, это периодический регистр сведений, измерения: Склад / Номенклатура / Характеристика, ресурс — Документ.ПриобретениеТоваровУслуг. В этом случае срез последних по всем измерениям с отбором по складам как раз даст вам последние документы. Если планируется получать данные по большей части на текущую дату, можно еще включить у регистра сведений итоги по срезу последних.
1С 8.3 : Как запросом получить последний по дате документ?
Сортируем документы по убыванию даты и используем конструкцию «ВЫБРАТЬ ПЕРВЫЕ 1»:
Код 1C v 8.х
В результате запрос вернёт одну строку, с данными последнего документа по одному контрагенту.
А как сделать запрос, который вернёт последние документы по всем контрагентам, а не по одному конкретному?
Используем функцию МАКСИМУМ в запросе для решения данной задачи.
Код 1C v 8.х
Этот запрос выбирает последние документы по всем контрагентам.
как в запросе выбрать самый последний документ
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
Промежуточная_ТЗ.Контрагент,
Промежуточная_ТЗ.Счет,
МАКСИМУМ(ХозрасчетныйОбороты.Регистратор) КАК Документ,
СУММА(Промежуточная_ТЗ.Дебет) КАК Дебет,
СУММА(Промежуточная_ТЗ.Кредит) КАК Кредит
ИЗ
Промежуточная_ТЗ КАК Промежуточная_ТЗ,
РегистрБухгалтерии.Хозрасчетный.Обороты(, &ДатаКон, Регистратор, Счет В ИЕРАРХИИ (&СписокСчетов), , Организация = &Организация, КорСчет В ИЕРАРХИИ (&СписокСчетов), ) КАК ХозрасчетныйОбороты
ГДЕ
(Промежуточная_ТЗ.Документ ЕСТЬ NULL
ИЛИ Промежуточная_ТЗ.Документ = НЕОПРЕДЕЛЕНО)
И Промежуточная_ТЗ.Счет = ХозрасчетныйОбороты.Счет
И Промежуточная_ТЗ.Контрагент = ХозрасчетныйОбороты.Субконто1
СГРУППИРОВАТЬ ПО
Промежуточная_ТЗ.Контрагент,
Промежуточная_ТЗ.Счет
УПОРЯДОЧИТЬ ПО
Документ УБЫВ
(4) упорядочил:
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
Промежуточная_ТЗ.Контрагент,
Промежуточная_ТЗ.Счет,
МАКСИМУМ(ХозрасчетныйОбороты.Регистратор.Дата) КАК ДокументДата,
МАКСИМУМ(ХозрасчетныйОбороты.Регистратор) КАК Документ,
СУММА(Промежуточная_ТЗ.Дебет) КАК Дебет,
СУММА(Промежуточная_ТЗ.Кредит) КАК Кредит
ИЗ
Промежуточная_ТЗ КАК Промежуточная_ТЗ,
РегистрБухгалтерии.Хозрасчетный.Обороты(, &ДатаКон, Регистратор, Счет В ИЕРАРХИИ (&СписокСчетов), , Организация = &Организация, КорСчет В ИЕРАРХИИ (&СписокСчетов), ) КАК ХозрасчетныйОбороты
ГДЕ
(Промежуточная_ТЗ.Документ ЕСТЬ NULL
ИЛИ Промежуточная_ТЗ.Документ = НЕОПРЕДЕЛЕНО)
И Промежуточная_ТЗ.Счет = ХозрасчетныйОбороты.Счет
И Промежуточная_ТЗ.Контрагент = ХозрасчетныйОбороты.Субконто1
СГРУППИРОВАТЬ ПО
Промежуточная_ТЗ.Контрагент,
Промежуточная_ТЗ.Счет
УПОРЯДОЧИТЬ ПО
ДокументДата УБЫВ
поля:
датадокумента документ
31.10.2012 23:59:59 операция 00001 от 31.01.2012:23 59 59
может так
ВЫБРАТЬ ПЕРВЫЕ 1
ИЗ
УПОРЯДОЧИТЬ ПО
Дата УБЫВ
Ладно уж, сорри тс, — потрите мои посты — это тяпница виновата 🙂
Если «без шуток», то в запросе «скрытая» ошибка. Желая получить дату и ссылку на последний документ — нельзя использовать максимум по дате и максимум по ссылке. Вы можете получить дату из одного документа и ссылку на другой документ.
ВЫБРАТЬ
ТоварыНаСкладах.Номенклатура КАК Номенклатура,
ТоварыНаСкладах.Регистратор КАК Регистратор,
ТоварыНаСкладах.Регистратор.Дата КАК Дата
ПОМЕСТИТЬ ТаблицаДвижений
ИЗ
РегистрНакопления.ТоварыНаСкладах КАК ТоварыНаСкладах
ГДЕ
ТоварыНаСкладах.Номенклатура = &Номенклатура
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
ТаблицаДвижений.Номенклатура,
МАКСИМУМ(ТаблицаДвижений.Дата) КАК Дата
ПОМЕСТИТЬ ТаблицаДат
ИЗ
ТаблицаДвижений КАК ТаблицаДвижений
СГРУППИРОВАТЬ ПО
ТаблицаДвижений.Номенклатура
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
ТаблицаДат.Номенклатура,
МАКСИМУМ(ТаблицаДвижений.Регистратор) КАК Регистратор
ИЗ
ТаблицаДат КАК ТаблицаДат
ЛЕВОЕ СОЕДИНЕНИЕ ТаблицаДвижений КАК ТаблицаДвижений
ПО ТаблицаДат.Дата = ТаблицаДвижений.Дата
СГРУППИРОВАТЬ ПО
ТаблицаДат.Номенклатура
(29) Грац — у меня мозг взорвался от просветления при чтении поста.
PS: я говорил про конкретный запрос, а не «в общем виде».
хотя на самом деле в (29) все равно используется максимум по ссылке. что не дает гарантию, что из двух документов с одинаковой датой выберется самый последний.
имхо самый правильный вариант:
получить в запросе отсортированную по Номенклатуре и МоментуВремени (убыв) таблицу ТАБЛ1
Номенклатура Регистратор МоментВремени
Пронумеровать строки в запросе.
Полученную ТАБЛ1 сгруппировать по Номенклатуре и Максимум по НомеруСтроки и сунуть в ТАБЛ2
Соединить ТАБЛ2 и ТАБЛ1 по номеру строки и получить регистратор (напримере соединения в (29))
Момент времени — это дата документа + номер таблицы вида документа + уникальный идентификатор документа. Ссылка — это номер таблицы + идентификатор. Так?
Имхо: сортировки по дате и ссылке с отбором первых/последних (от сортировки зависит) — достаточно.
(37) получилось так
ВЫБРАТЬ
МАКСИМУМ(ХозрасчетныйОбороты.Регистратор.Дата) КАК РегистраторДата,
ХозрасчетныйОбороты.Счет,
ХозрасчетныйОбороты.Субконто1
ПОМЕСТИТЬ ПоследниеДокументыНаДату
ИЗ
РегистрБухгалтерии.Хозрасчетный.Обороты(, &КонДата, Регистратор, Счет = &Счет, , , , ) КАК ХозрасчетныйОбороты
СГРУППИРОВАТЬ ПО
ХозрасчетныйОбороты.Счет,
ХозрасчетныйОбороты.Субконто1
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
МАКСИМУМ(ХозрасчетныйОбороты.Регистратор) КАК Регистратор,
ХозрасчетныйОбороты.Счет,
ХозрасчетныйОбороты.Субконто1 КАК Субконто1
ИЗ
РегистрБухгалтерии.Хозрасчетный.Обороты(, , Регистратор, , , , , ) КАК ХозрасчетныйОбороты
ВНУТРЕННЕЕ СОЕДИНЕНИЕ ПоследниеДокументыНаДату КАК ПоследниеДокументыНаДату
ПО ХозрасчетныйОбороты.Счет = ПоследниеДокументыНаДату.Счет
И ХозрасчетныйОбороты.Субконто1 = ПоследниеДокументыНаДату.Субконто1
И ХозрасчетныйОбороты.Регистратор.Дата = ПоследниеДокументыНаДату.РегистраторДата
СГРУППИРОВАТЬ ПО
ХозрасчетныйОбороты.Счет,
ХозрасчетныйОбороты.Субконто1
УПОРЯДОЧИТЬ ПО
Субконто1,
Регистратор
но почему-то этот запрос медленее отрабатывает по сравнению с тем если получить все документы по оборотам 60.01(в случае с программной обработкой результата запроса)
ВЫБРАТЬ
ХозрасчетныйОбороты.Регистратор КАК Регистратор,
ХозрасчетныйОбороты.Счет,
ХозрасчетныйОбороты.Субконто1 КАК Субконто1
ИЗ
РегистрБухгалтерии.Хозрасчетный.Обороты(, &КонДата, Регистратор, , , , , ) КАК ХозрасчетныйОбороты
ГДЕ
ХозрасчетныйОбороты.Счет = &Счет
СГРУППИРОВАТЬ ПО
ХозрасчетныйОбороты.Счет,
ХозрасчетныйОбороты.Субконто1,
ХозрасчетныйОбороты.Регистратор
1С выбрать последнюю запись в запросе
В данной статье рассмотрено предложение ВЫБРАТЬ, его место и роль в языке запросов 1С:Предприятия 8.
Предложение ВЫБРАТЬ является единственным обязательным элементом любого запроса, поэтому изучение языка запросов начинается именно с него. Основная цель предложения ВЫБРАТЬ заключается в том, чтобы указать поля выборки, которые должны попасть в результат запроса.
Ниже рассмотрены следующие темы:
Место предложения ВЫБРАТЬ в структуре запроса
Структуру запроса 1С:Предприятия 8 можно представить в виде следующей схемы:
Из приведенной схемы можно сделать следующие выводы:
- В любом запросе должно быть хотя бы одно предложение ВЫБРАТЬ.
- В списке полей выборки должно быть описание хотя бы одного поля выборки, которое в общем случае является выражением.
Примеры запросов с предложением ВЫБРАТЬ
1. Выборка всех полей (кроме виртуальных) из таблиц
Вместо перечисления списка полей можно указать звездочку ("*") и тогда в результат запроса попадут все поля таблицы-источника, кроме виртуальных. Например:
//обращение к таблице справочника
ВЫБРАТЬ * ИЗ Справочник.Номенклатура
//обращение к таблице документа
ВЫБРАТЬ * ИЗ Документ.РасходныйКассовыйОрдер
//обращение к основной таблице регистра накопления
ВЫБРАТЬ * ИЗ РегистрНакопления.ПродажиКомпании
//обращение к виртуальной таблице регистра накопления
ВЫБРАТЬ * ИЗ РегистрНакопления.ПродажиКомпании.Обороты
Замечание: В языке запросов есть возможность обойтись без предложения ИЗ, если описание поля содержит полный путь к нему с указанием таблицы-источника, например,
//выборка всех невиртуальных полей из таблицы справочника
ВЫБРАТЬ Справочник.Номенклатура.*
//выборка определенных полей из таблицы справочника
ВЫБРАТЬ
Справочник.Номенклатура.Код,
Справочник.Номенклатура.Наименование,
Справочник.Номенклатура.Представление //виртуальное поле
2. Выборка только определенных полей из таблиц
Самым обычным способом является перечисление нескольких полей из таблицы-источника запроса, тогда только эти поля попадут в результат запроса.
//обращение к таблице справочника
ВЫБРАТЬ Код, Наименование, Артикул, СтранаПроисхождения
ИЗ Справочник.Номенклатура
//обращение к таблице документа
ВЫБРАТЬ Номер, Дата, ПодразделениеКомпании, СуммаДокумента
ИЗ Документ.РасходныйКассовыйОрдер
3. Виртуальные поля
Некоторые поля в таблицах-источниках виртуальные, например, поле «Представление» для таблицы справочника и документа, или поле «МоментВремени» для документа. Это значит, что они не хранятся в базе данных, а генерируются «на лету». Виртуальные поля не включаются в результат запроса, когда вместо списка полей указана звездочка («*»), их нужно указывать явно, например «ВЫБРАТЬ *, Представление ИЗ Справочник.Товары». Такое решение было принято для ускорения выполнения классического запроса «ВЫБРАТЬ * ИЗ. ». В этом случае не требуется генерировать представления для элементов справочников и документов, следовательно запросы будут выполняться быстрее.
//обращение к таблице справочника (выбрать два обычных поля и одно виртуальное)
ВЫБРАТЬ Код, Наименование, Представление
ИЗ Справочник.Номенклатура
//обращение к таблице документа (выбрать все невиртуальные поля и два виртуальных)
ВЫБРАТЬ *, Представление, МоментВремени
ИЗ Документ.РасходныйКассовыйОрдер
4. Разыменование ссылочных полей
В 1С:Предприятии 8 допускается обращение к свойствам объектов через одну или несколько точек, например, «Номенклатура.Поставщик.Страна». Это позволяет значительно упростить написание запросов. Рекомендуется всегда пользоваться разыменованием полей там, где это возможно, чтобы не усложнять запросы лишними конструкциями.
//обращение к свойству объекта через одну точку
ВЫБРАТЬ
Ссылка,
ЮрФизЛицоКонтрагента . ИНН,
ПодразделениеКомпании . Код
ИЗ Документ.РасходныйКассовыйОрдер
//обращение к свойствам объектов через несколько точек
ВЫБРАТЬ
Ссылка,
Ответственный . ОсновнойБанковскийСчет . Банк . КоррСчет
ИЗ Документ.АвансовыйОтчет
5. Псевдонимы полей (ключевое слово КАК / AS)
Для поля может быть назначен псевдоним с помощью ключевого слова КАК. Это позволяет обращаться к полю по псевдониму при указании итогов и порядка сортировки, а также при обходе выборки из результата запроса, например:
ВЫБРАТЬ
Ссылка КАК Документ,
Ответственный КАК МатериальноОтветственный
ИЗ Документ.АвансовыйОтчет
УПОРЯДОЧИТЬ ПО МатериальноОтветственный
Ключевое слово КАК является необязательным, то есть вышеприведенный запрос можно записать так:
ВЫБРАТЬ
Ссылка Документ,
Ответственный МатериальноОтветственный
ИЗ Документ.АвансовыйОтчет
6. Обращение к табличной части как вложенной таблице
В этом случае поле результата запроса будет иметь тип РезультатЗапроса, то есть содержать вложенный результат запроса, сформированный на основе табличной части.
//получение табличной части как вложенной таблицы результата запроса
ВЫБРАТЬ Номер, Дата, Товары
ИЗ Документ.АвансовыйОтчет
//получение нескольких колонок табличной части как вложенной таблицы
ВЫБРАТЬ Номер, Дата, Товары.(Номенклатура, Количество)
ИЗ Документ.АвансовыйОтчет
Обратите внимание, что если выполнить следующий запрос, то в результате запроса будет две вложенные таблицы: в первой — одна колонка Номенклатура, а во второй — колонка Количество:
ВЫБРАТЬ Номер, Дата, Товары.Номенклатура, Товары.Количество
ИЗ Документ.АвансовыйОтчет
7. Обращение к табличной части как таблице-источнику
При таком способе обращения имя вложенной таблицы фигурирует в имени таблицы-источника (предложение ИЗ или полные имена полей) и в результате запроса нет вложенных таблиц.
//выборка всех полей из табличной части
ВЫБРАТЬ * ИЗ Документ.АвансовыйОтчет.Товары
// выборка определенных полей из табличной части
ВЫБРАТЬ Номенклатура, Количество, Цена, Сумма
ИЗ Документ.АвансовыйОтчет.Товары
//задание псевдонимов для полей табличной части
ВЫБРАТЬ Документ.АвансовыйОтчет.Товары.(Номенклатура, Сумма КАК СуммаПоСтроке)
//обращение к реквизитам документа и реквизитам табличной части (поле Ссылка)
ВЫБРАТЬ
Ссылка.Номер, Ссылка.Дата, Ссылка.Ответственный, //реквизиты документа
Номенклатура, Количество, Цена, Сумма //реквизиты табличной части
ИЗ Документ.АвансовыйОтчет.Товары
8. Ключевое слово РАЗЛИЧНЫЕ / DISTINCT
Ключевое слово РАЗЛИЧНЫЕ позволяет оставить в результате запроса только отличающиеся строки.
ВЫБРАТЬ РАЗЛИЧНЫЕ Ответственный
ИЗ Документ.АвансовыйОтчет
9. Ключевое слово ПЕРВЫЕ / TOP
Данное ключевое слово позволяет ограничить выборку несколькими первыми записями. Часто это ключевое слово применяется в комбинации с сортировкой (предложение УПОРЯДОЧИТЬ ПО).
ВЫБРАТЬ ПЕРВЫЕ 10 Номер, Дата, СуммаДокумента
ИЗ Документ.АвансовыйОтчет
УПОРЯДОЧИТЬ ПО СуммаДокумента УБЫВ
10. Выражения в списке полей выборки
В качестве описания поля выборки может быть выражение, использующее следующие элементы:
- Литералы типов: число, строка (в кавычках), булево (значения Истина и Ложь), Null, Неопределено. [ Замечание : Чтобы указать литерал типа "дата", можно воспользоваться ключевым словом языка запросов ДАТАВРЕМЯ или передать дату через параметр запроса].
- Параметры запроса (со знаком &)
- Имя поля
- Имя табличной части
- Разыменование ссылочного поля (через одну или несколько точек)
- Арифметические операции (+, -, /, *) [ Замечание : операция получения остатка % в языке запросов не поддерживается]
- Операция конкатенации строк (+) [ Замечание : операцию конкатенации нельзя использовать для виртуальных полей]
- Встроенные функции языка запросов (ДЕНЬ, МЕСЯЦ, ГОД и т.д.)
- Агрегатные функции (СУММА, МИНИМУМ, МАКСИМУМ, СРЕДНЕЕ, КОЛИЧЕСТВО)
- Операция выбора ВЫБОР / CASE — позволяет получить одно из возможных значений в соответствии с указанными условиями.
- Операция приведения типов ВЫРАЗИТЬ / CAST
Ниже приведено несколько примеров с выражениями в списке полей выборки:
//арифметические операции
ВЫБРАТЬ
Номенклатура,
Количество * Цена КАК РасчСумма1,
Сумма / Количество КАК РасчСумма2
ИЗ Документ.АвансовыйОтчет.Товары
//литералы типа "булево", "число", "строка", "дата"
ВЫБРАТЬ Истина, Ложь, 10.5, "Текст", ДАТАВРЕМЯ(2003,12,25)
//конкатенация строк
ВЫБРАТЬ "Сотрудник " + Ответственный.Наименование
ИЗ Документ.АвансовыйОтчет
//агрегатные функции
ВЫБРАТЬ
ПодразделениеКомпании,
СУММА(СуммаДокумента),
МАКСИМУМ(СуммаДокумента),
МИНИМУМ(СуммаДокумента),
СРЕДНЕЕ(СуммаДокумента),
КОЛИЧЕСТВО(*)
ИЗ Документ.АвансовыйОтчет
СГРУППИРОВАТЬ ПО ПодразделениеКомпании
//операция выбора
ВЫБРАТЬ Наименование,
ВЫБОР
КОГДА СтранаПроисхождения.Наименование = "КИТАЙ" ТОГДА "Азия"
КОГДА СтранаПроисхождения.Наименование = "ТАЙВАНЬ" ТОГДА "Азия"
КОГДА СтранаПроисхождения.Наименование = "США" ТОГДА "Америка"
КОГДА СтранаПроисхождения.Наименование = "КАНАДА" ТОГДА "Америка"
ИНАЧЕ "Другое"
КОНЕЦ КАК Страна
ИЗ Справочник.Номенклатура
//операция приведения типов
ВЫБРАТЬ
Ссылка,
Номенклатура,
ВЫРАЗИТЬ(Сумма / 3 КАК Число(5,2)) КАК ТретьСуммы
ИЗ Документ.АвансовыйОтчет.Товары
Таким образом, предложение ВЫБРАТЬ является важнейшим элементом языка запросов, поскольку позволяет указать требуемые поля результата запроса. Гибкие возможности предложения ВЫБРАТЬ позволяют использовать язык запросов для решения самых разнообразных задач.
Сортируем документы по убыванию даты и используем конструкцию «ВЫБРАТЬ ПЕРВЫЕ 1»:
Код 1C v 8.х
В результате запрос вернёт одну строку, с данными последнего документа по одному контрагенту.
А как сделать запрос, который вернёт последние документы по всем контрагентам, а не по одному конкретному?
Используем функцию МАКСИМУМ в запросе для решения данной задачи.
Код 1C v 8.х
Этот запрос выбирает последние документы по всем контрагентам.
Имеется таблица, содержащая, например, колонки Ф, К1, К2, К3, К4. Для каждого значения Ф в тоблице может быть несколько записей.
Ф | К1 | К2 | К3 | К4 |
Петя | 1 | 1 | 1 | 1 |
Петя | 2 | 0 | 0 | 0 |
Петя | 3 | 0 | 0 | 0 |
Вася | 5 | 5 | 5 | 5 |
Женя | 4 | 4 | 4 | 4 |
Требуется получить таблицу, включающую по одной (любой) записи для каждого значения Ф.
Ф | К1 | К2 | К3 | К4 |
Петя | 1 | 1 | 1 | 1 |
Вася | 5 | 5 | 5 | 5 |
Женя | 4 | 4 | 4 | 4 |
Несмотря на простоту формлировки, у задачи нет простого решения, если только не использовать коррелированный запрос. С использованием коррелированного запроса решение получается очень простым:
ВЫБРАТЬ РАЗЛИЧНЫЕ Ф , К1 , К2 , К3 , К4
ИЗ Дано
ГДЕ ( Ф , К1 , К2 , К3 , К4 )
В ( ВЫБРАТЬ ПЕРВЫЕ 1 * ИЗ Дано КАК ВС Ё ГДЕ ВС Ё . Ф = Дано . Ф )
При использовании коррелированных запросов нельзя забывать о подводных камнях этого механизма, в частности о том, что он может служить причиной падения производительности запроса. Кроме того, в некоторых версиях файлового варианта условие ГДЕ из-за ошибки платформы 8.2 не срабатывает.