Жаропонижающие средства для детей назначаются педиатром. Но бывают ситуации неотложной помощи при лихорадке, когда ребенку нужно дать лекарство немедленно. Тогда родители берут на себя ответственность и применяют жаропонижающие препараты. Что разрешено давать детям грудного возраста? Чем можно сбить температуру у детей постарше? Какие лекарства самые безопасные?
В тестовой конфигурации в журнале документов необходимо реализовать нумерацию строк в динамическом списке. В журнал входит три документа: "Заявка", "Приходный ордер" и "Расходный ордер". Первоначально форма списка журнала документов выглядит следующим образом:
В принципе, задача легко бы решалась, если список документов мы бы получали в отчете. Но тут дела обстоят иначе.
В отчетах - не проблема!
Создав отчет на системе компоновки данных с получением списка документов, задача решалась бы очень просто. В поля отчета нужно было бы всего-навсего добавить специальное поле "Номер по порядку".
В результате пользователь увидит подобный результат формирования отчета:
Но как быть, если нумерацию нужно получить непосредственно в запросе? Например, это может понадобиться для получения порядкового номера записи в динамическом списке.
Нумерация в запросе
Изменим запрос динамического списка журнала документов следующим образом:
" ВЫБРАТЬ | Т. НомерПоПорядку, | Т. Ссылка, | Т. Дата, | Т. ПометкаУдаления, | Т. Номер, | Т. Проведен, | Т. Тип |ИЗ | (ВЫБРАТЬ " + // Получаем количество присоединенных ссылок в поле "НомерПоПорядку" " КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ЖурналДокументовЖурналДокументов. Ссылка) КАК НомерПоПорядку, | ЖурналДокументов. Ссылка КАК Ссылка, | ЖурналДокументов. Дата КАК Дата, | ЖурналДокументов. ПометкаУдаления КАК ПометкаУдаления, | ЖурналДокументов. Номер КАК Номер, | ЖурналДокументов. Проведен КАК Проведен, | ЖурналДокументов. Тип КАК Тип | ИЗ | ЖурналДокументов. ЖурналДокументов КАК ЖурналДокументов | ЛЕВОЕ СОЕДИНЕНИЕ ЖурналДокументов. ЖурналДокументов КАК ЖурналДокументовЖурналДокументов " + // Соединим таблицу журнала документов к самой себе по ссылке на документ. Количество присоед. // ссылок и есть порядковый номер " ПО ЖурналДокументов. Ссылка > = ЖурналДокументовЖурналДокументов. Ссылка / | | СГРУППИРОВАТЬ ПО | ЖурналДокументов. Ссылка, | ЖурналДокументов. Дата, | ЖурналДокументов. ПометкаУдаления, | ЖурналДокументов. Номер, | ЖурналДокументов. Проведен, | ЖурналДокументов. Тип) КАК Т "При открытии динамического списка в режиме 1С:Предприятия получаем следующий результат:
Примечание: в примере показан лишь принцип нумерации строк непосредственно в запросе. Если Вы обратили внимание, то на скриншоте выше документы в списке, отсортированные по порядковому номеру строки, "идут" в порядке типов (сначала приходные ордера, затем расходные и т.д.). Это происходит, потому что, используя ссылку для соединения, мы не можем гарантировать, что GUID"ы ссылок будут уникальными. Также нельзя сравнивать ссылки разных типов документов - это приведет к некорректному результату. Можно использовать момент времени или другие поля, определяющие конкретное положение документа с общем списке журнала.
Конечно, используя подобный подход мы усложнили бы запрос к базе данных, плюс ко всему, некоторые возможности динамического списка, важные для работы пользователей, стали бы не доступными (динамическое считывание данных, основная таблица и т.д.), но пример был создан лишь для демонстрации возможности нумерации строк в запросах. Используя этот принцип для решения других задач, например для печатных форм, подобных проблем не возникнет.
Нужно понимать, что использование повторного обращения к таблице документа или журнала документов может отрицательно повлиять на производительность. Оптимальным было бы создание временной таблицы всех выбираемых документов, а затем уже работать с ней. Опять же, все зависит от конкретной задачи!
Остальные рассмотрим сейчас.
Функции работы со строками в запросах 1С
Функций и операторов для работы со строковыми данными в запросах 1С немного.
Во-первых, строки в запросах можно складывать. Для этого используется оператор «+»:
Запрос.
Текст=
"ВЫБРАТЬ
"
"Строка: "
" + Источник.Наименование
;
Во-вторых, можно выделить часть строки. Для этого используется функция ПОДСТРОКА. Функция аналогична встроенного языка 1С. У нее три параметра:
- Строка-источник.
- Номер символа, с которого должна начинаться выделяемая строка.
- Количество символов.
Запрос.
Текст=
"ВЫБРАТЬ
ПОДСТРОКА("
"Строка: "
", 4, 3) КАК Результат"
;
// Результат: ока
Функция ЕСТЬNULL
NULL — особый тип данных на платформе 1С:Предприятие. Он же является единственным возможным значением этого типа. NULL может возникать в запросах в нескольких случаях: при соединениях источников запроса, если не было найдено соответствующего значения в одной из таблиц; при обращении к реквизитам несуществующего объекта; если NULL был указан в списке полей запроса (например при объединении результатов выборки из нескольких таблиц) и т.д.
Поскольку NULL не является ни нулем, ни пустой строкой, ни даже значением Неопределено, его часто бывает полезно заменять на какой-то более полезный тип данных. Для этого и предназначена функция ЕСТЬNULL.
Она имеет два параметра:
- Проверяемое значение.
- Значение, на которое нужно заменить первый параметр, если он оказался равен NULL.
Запрос.
Текст=
"ВЫБРАТЬ
ЕСТЬNULL(Источник.Остаток, 0) КАК Остаток"
;
// Если в результате запроса поле остаток=NULL,
// то оно заменится на 0, и с ним можно будет выполнять математические действия
Функции ПРЕДСТАВЛЕНИЕ и ПРЕДСТАВЛЕНИЕССЫЛКИ
Эти функции предназначены для получения строковых представлений различных значений. То есть, они преобразуют ссылки, числа, булево и т.д. в обычный текст. Разница между ними в том, что функция ПРЕДСТАВЛЕНИЕ преобразует в текст (строку) любые типы данных, а функция ПРЕДСТАВЛЕНИЕССЫЛКИ — только ссылки, а остальные значения возвращает как есть, не преобразованными.
Запрос.
Текст=
"ВЫБРАТЬ
ПРЕДСТАВЛЕНИЕ (ИСТИНА) КАК Булево,
ПРЕДСТАВЛЕНИЕ (4) КАК Число,
ПРЕДСТАВЛЕНИЕ (Источник.Ссылка) КАК Ссылка,
ПРЕДСТАВЛЕНИЕ(ДАТАВРЕМЯ(2016,10,07)) КАК Дата"
;
// Булево = "Да", Число = "4", Ссылка = "Документ Расходный кассовый ордер №... от..."
// Дата="07.10.2016 0:00:00"
Запрос.
Текст=
"ВЫБРАТЬ
ПРЕДСТАВЛЕНИЕССЫЛКИ (ИСТИНА) КАК Булево,
ПРЕДСТАВЛЕНИЕССЫЛКИ (4) КАК Число,
ПРЕДСТАВЛЕНИЕССЫЛКИ (Источник.Ссылка) КАК Ссылка,
ПРЕДСТАВЛЕНИЕССЫЛКИ (ДАТАВРЕМЯ(2016,10,07)) КАК Дата"
;
// Булево = ИСТИНА, Число = 4, Ссылка = "Документ Расходный кассовый ордер №... от..."
// Дата=07.10.2016 0:00:00
Функции ТИП и ТИПЗНАЧЕНИЯ
Функция ТИП возвращает тип данных платформы 1С:Предприятие.
Запрос.
Текст=
"ВЫБРАТЬ
ТИП (Число) ,
ТИП (Строка),
ТИП (Документ.РасходныйКассовыйОрдер)"
;
Функция ТИПЗНАЧЕНИЯ возвращает тип переданного в нее значения.
Запрос.
Текст=
"ВЫБРАТЬ
ТИПЗНАЧЕНИЯ (5) КАК Число,
ТИП ("
"Строчка"
") КАК Строка,
ТИП (Источник.Ссылка) КАК Справочник
Из Справочник.Источник КАК Источник"
;
//Число=Число, Строка=Строка, Справочник = СправочникСсылка.Источник
Эти функции удобно применять, например, когда нужно выяснить является ли полученное в запросе поле значением какого-то типа. Например, получим контактную информацию контрагентов из регистра сведений КонтактнаяИнформация (там хранятся контакты не только контрагентов, но и организаций, физических лиц и т.д.):
Запрос.
Текст=
"ВЫБРАТЬ
ИЗ
ГДЕ
ТИПЗНАЧЕНИЯ(КонтактнаяИнформация.Объект) = ТИП(Справочник.Контрагенты)"
;
Функция ЗНАЧЕНИЕ
Функция Значение позволяет использовать в запросе объекты конфигурации 1С напрямую, без применения .
Дополним предыдущий пример еще одним условием. Необходимо получить только телефоны контрагентов.
Запрос.
Текст=
"ВЫБРАТЬ
КонтактнаяИнформация.Представление
ИЗ
РегистрСведений.КонтактнаяИнформация КАК КонтактнаяИнформация
ГДЕ
ТИПЗНАЧЕНИЯ(КонтактнаяИнформация.Объект) = ТИП(Справочник.Контрагенты)
И КонтактнаяИнформация.Тип = ЗНАЧЕНИЕ(Перечисление.ТипыКонтактнойИнформации.Телефон)"
;
Следует отметить, что эту функцию можно использовать только с предопределенными значениями, т.е. со значениями, к которым можно обратиться напрямую из конфигуратора. То есть функция ЗНАЧЕНИЕ не можно использоваться с элементами справочников, созданными пользователями, но может работать с перечислениями, с предопределенными элементами справочников, со значениями ПустаяСсылка .
Оператор ССЫЛКА
Оператор ССЫЛКА предназначен для проверки значений, получаемых запросом, на принадлежность к определенному ссылочному типу. Эту же задачу можно выполнить с помощью функций ТИП и ТИПЗНАЧЕНИЯ (которые имеют более широкую область применения и были рассмотрены выше).
Например, задачу выбора контактной информации контрагентов можно было решить и так:
Запрос.
Текст=
"ВЫБРАТЬ
КонтактнаяИнформация.Представление
ИЗ
РегистрСведений.КонтактнаяИнформация КАК КонтактнаяИнформация
ГДЕ
КонтактнаяИнформация.Объект ССЫЛКА Справочник.Контрагенты"
;
Оператор ВЫРАЗИТЬ
Оператор ВЫРАЗИТЬ используется в запросах 1С в двух случаях:
- когда нужно изменить характеристики примитивного типа;
- когда нужно из поля с составным типом данных сделать поле с одиночным типом.
К примитивным типам данных относятся: число, строка, дата, булево. Некоторые из этих типов данных имеют дополнительные характеристики. Тип Число имеет длину и точность, тип Строка — длину или неограниченность.
Оператор ВЫРАЗИТЬ позволяет изменять не тип данных, а именно дополнительные характеристики. Например, он может из строки с неограниченной длиной сделать строку с длиной ограниченной. Это бывает полезно, если нужно сгруппировать результаты запроса по такому полю. Выполнять группировку по полям с неограниченной длиной нельзя, поэтому мы его преобразуем в строку с длиной 200 символов.
Запрос.
Текст=
"ВЫБРАТЬ
КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ПоступлениеТоваровУслуг.Ссылка) КАК Ссылка
ИЗ
Документ.ПоступлениеТоваровУслуг КАК ПоступлениеТоваровУслуг
СГРУППИРОВАТЬ ПО
ВЫРАЗИТЬ(ПоступлениеТоваровУслуг.Комментарий КАК СТРОКА(200))"
;
В ряде случаев, запросы к полям с составным типом данных могут обрабатываться платформой 1С неоптимально. Это приводит к увеличению времени выполнения запросов, поэтому бывает полезно заранее преобразовать составной тип в одиночный.
Запрос.
Текст=
"ВЫБРАТЬ
ВЫРАЗИТЬ(ДвижениеТоваровОбороты.Распоряжение КАК Документ.ЗаказКлиента).Дата КАК ДатаЗаказа,
ДвижениеТоваровОбороты.Номенклатура
ИЗ
РегистрНакопления.ДвижениеТоваров.Обороты КАК ДвижениеТоваровОбороты
ГДЕ
ДвижениеТоваровОбороты.Распоряжение ССЫЛКА Документ.ЗаказКлиента"
;
Операторы ВЫБОР и ЕСТЬ NULL
Оператор ВЫБОР аналогичен оператору ЕСЛИ во встроенном языке 1С, но имеет несколько урезанный функционал.
Допустим мы хотим получить контактные данные из регистра сведений КонтактнаяИнформация и при этом в отдельном поле запроса указать, принадлежат ли они контрагенту или физическому лицу.
Запрос.
Текст=
"ВЫБРАТЬ
КонтактнаяИнформация.Представление,
ВЫБОР
КОГДА ТИПЗНАЧЕНИЯ(КонтактнаяИнформация.Объект) = ТИП(Справочник.Контрагенты)
ТОГДА "
Контрагент"
ИНАЧЕ ВЫБОР
КОГДА ТИПЗНАЧЕНИЯ(КонтактнаяИнформация.Объект) = ТИП(Справочник.ФизическиеЛица)
ТОГДА "
ФизЛицо"
ИНАЧЕ "
Кто-
то другой"
КОНЕЦ
КОНЕЦ КАК Владелец
ИЗ
РегистрСведений.КонтактнаяИнформация КАК КонтактнаяИнформация"
;
Как видно из примера, в конструкции ВЫБОР всегда присутствует условие после слова КОГДА; значение, применяемое, если условие выполняется, после слова ТОГДА и значение, применяемое, если условие не выполняется, после слова ИНАЧЕ. Все три элемента конструкции ВЫБОР являются обязательными. Опустить элемент ИНАЧЕ , так же, как это делается при использовании оператора ЕСЛИ во встроенном языке 1С, нельзя. Также у оператора ВЫБОР отсутствует аналог конструкции ИНАЧЕЕСЛИ , зато можно вложить один ВЫБОР в другой, как и было сделано в нашем примере.
Оператор ЕСТЬ NULL используется в конструкции ВЫБОР для сравнения поля запроса с типом NULL.
Запрос.
Текст=
"ВЫБРАТЬ
ВЫБОР
КОГДА Значение ЕСТЬ NULL ТОГДА 0
ИНАЧЕ Значение
КОНЕЦ"
;
Кроме того, оператор ЕСТЬ NULL можно использовать в условиях запроса, например в предложении ГДЕ.
Ключевые слова: нумерация строк запроса, ПЕРВЫЕ, нумерация строк в построителе, пронумеровать
Иногда возникает необходимость добавить в запрос колонку с номерами строк, например, когда нужно вывести номера строк в отчет, а используется построитель отчета. Так же нумерация строк полезна когда необходимо для определенных группировок вывести ограниченное количество строк данных. Что-то типа ПЕРВЫЕ 5 документов для каждого контрагента.
Итак, есть код, выбирающий номенклатуру, отсортированный по наименованию:
ВЫБРАТЬ
Номенклатура.Ссылка
ИЗ
УПОРЯДОЧИТЬ ПО
Номенклатура.Наименование
исходный запрос
Требуется добавить сюда колонку с порядковыми номерами номенклатуры (в рамках данной сортировки).
ВЫБРАТЬ
ИЗ
Справочник.Номенклатура КАК Номенклатура
ПО Номенклатура.Наименование >= Номенклатура_1.Наименование // Условие сортировки для нумерации
УПОРЯДОЧИТЬ ПО
Номенклатура.Наименование
запрос с номерами строк
Соединяем таблицу саму с собой довольно хитрым способом. По правой таблице подсчитываем количество номенклатуры с наименованием меньше текущего левого, используя группировку.
Аналогичную технику можно применить, если нужно задавать нумерацию строк с учетом группировки по какому-то полю.
ВЫБРАТЬ
Номенклатура.Ссылка КАК Номенклатура,
Номенклатура.Родитель КАК Родитель,
КОЛИЧЕСТВО(Номенклатура_1.Ссылка) КАК Номер
ИЗ
Справочник.Номенклатура КАК Номенклатура
ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК Номенклатура_1
ПО Номенклатура.Наименование >= Номенклатура_1.Наименование
И Номенклатура.Родитель = Номенклатура_1.Родитель
СГРУППИРОВАТЬ ПО
Номенклатура.Родитель,
Номенклатура.Ссылка
запрос с номерами строк в рамках группировки
Это тот же самый запрос, в него просто добавлена группировка по полю "Родитель", нумерация для каждого родителя своя.
Быстродействие:
Если говорить о быстродействии, то запросы подобного рода естественно ресурсоемки (математически ложность порядка N^2). Для большинства повседневных задач их использование вполне приемлемо.
Кстати, второй запрос выполняется несколько быстрее первого, это связано с меньшим размером вспомогательных таблиц.
Пример реального использования:
Теперь немного о том, ради чего всё это делается, то-есть польза, которую можно извлечь из нумерации строк запроса.
Например, перед нами стоит задача получить для каждого контрагента пять последних документов поступления товаров и услуг:
ВЫБРАТЬ
ПоступлениеТоваровУслуг.Контрагент КАК Контрагент,
ПоступлениеТоваровУслуг.Ссылка КАК Ссылка,
КОЛИЧЕСТВО(ПоступлениеТоваровУслуг_1.Ссылка) КАК Номер
ИЗ
Документ.ПоступлениеТоваровУслуг КАК ПоступлениеТоваровУслуг
ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.ПоступлениеТоваровУслуг КАК ПоступлениеТоваровУслуг_1
ПО ПоступлениеТоваровУслуг.Дата <= ПоступлениеТоваровУслуг_1.Дата
И ПоступлениеТоваровУслуг.Контрагент = ПоступлениеТоваровУслуг_1.Контрагент
СГРУППИРОВАТЬ ПО
ПоступлениеТоваровУслуг.Ссылка,
ПоступлениеТоваровУслуг.Контрагент
ИМЕЮЩИЕ
КОЛИЧЕСТВО(ПоступлениеТоваровУслуг_1.Ссылка) <= 5
УПОРЯДОЧИТЬ ПО
Контрагент,
Номер
запрос с номерами строк при наличии дублей интересующего поля(того,относительно которого строится счетчик)
ВЫБРАТЬ
КОЛИЧЕСТВО(ФизическиеЛица_1.Наименование) КАК Номер,
ФизическиеЛица.Ссылка КАК ФИО
ИЗ
Справочник.ФизическиеЛица КАК ФизическиеЛица
ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.ФизическиеЛица КАК ФизическиеЛица_1
ПО (ФизическиеЛица.Наименование + ФизическиеЛица.Код >= ФизическиеЛица_1.Наименование + ФизическиеЛица_1.Код)
УПОРЯДОЧИТЬ ПО
Номер
Собственно говоря идея какова: использовать "составное поле" для получения возрастающего итога (при этом одно поле может содержать дубли, а второе в данном примере- нет.)
Родилось в голове НЕКРОН"а