Синтаксическая ошибка сумма

Всем день добрый! Никак не возьму в толк, чего не так в запросе. Пытаюсь получить итоговую сумму по реестру документов. Однако, выдаётся ошибка:

{Форма.ФормаОтчета(54)}: Ошибка при вызове метода контекста (Выполнить): {(9, 1)}: Синтаксическая ошибка «СУММА(ИтогДокумента)»

<<?>>СУММА(ИтогДокумента) как ИтогСумма

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

по причине:

{(9, 1)}: Синтаксическая ошибка «СУММА(ИтогДокумента)»

<<?>>СУММА(ИтогДокумента) как ИтогСумма

В чём ошибка в столь примитивном тексте?

Запрос.Текст =        

   «ВЫБРАТЬ

   
   |Документ.Ссылка КАК Ссылка,

   |Документ.ПометкаУдаления,

   |Документ.Номер КАК НомерДока,

   |Документ.Ссылка.Дата КАК ДатаДока,

   |Документ.Проведен,

   |Документ.Контрагент.Наименование КАК Контрагент,

   |Документ.СуммаДокумента КАК ИтогДокумента

   
   |СУММА(ИтогДокумента) как ИтогСумма    

   
   |ИЗ

   |»+ДокВид+» как Документ

   
   |Где

   |(Документ.Ссылка.Дата МЕЖДУ &ДатаНач И &ДатаКон) и НЕ (Документ.Ссылка.ПометкаУдаления)

   
   //|Итоги СУММА(ИтогДокумента) как СуммаИтог    // И так тоже пробовал

   //|По Документ.ПометкаУдаления

   
   |УПОРЯДОЧИТЬ ПО

   |ДатаДока,

   |Ссылка»;

Gokusa

Заблокирован

1

«ИТОГИ» синтаксическая ошибка

24.12.2012, 14:45. Показов 7989. Ответов 27

Метки нет (Все метки)


Студворк — интернет-сервис помощи студентам

пишу

1C
1
2
3
4
5
6
7
8
9
ВЫБРАТЬ
    ПродажиОбороты.Товар,
    ПродажиОбороты.Склад,
    ПродажиОбороты.КоличествоОборот 
ИЗ
    РегистрНакопления.Продажи.Обороты КАК ПродажиОбороты,
 
    
    ИТОГИ Сумма(количествооборот) по товар

рурается на итоги — пишет «ожидается имя таблицы»
если написать упорядочить по бла бла бла, тогда не ругается, но пишет «синтаксическая ошибка » но уже перед сумма()
в чём ошибка?



0



Programming

Эксперт

94731 / 64177 / 26122

Регистрация: 12.04.2006

Сообщений: 116,782

24.12.2012, 14:45

27

Модератор

Эксперт 1С

3722 / 2917 / 574

Регистрация: 10.03.2011

Сообщений: 11,489

Записей в блоге: 1

24.12.2012, 14:49

2

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

ИТОГИ Сумма(КоличествоОборот) по товар



0



Gokusa

Заблокирован

24.12.2012, 14:53

 [ТС]

3

так тоже не работает
к тому же он сам дописвает такие огрехи если чё

Добавлено через 2 минуты

1C
1
2
3
4
5
6
7
8
9
10
ВЫБРАТЬ
    ПродажиОбороты.Товар как т,
    ПродажиОбороты.Склад как с,
    ПродажиОбороты.КоличествоОборот КАК Ко
ИЗ
    РегистрНакопления.Продажи.Обороты КАК ПродажиОбороты,
 
    итоги 
    сумма(ко)
     по т

ожидается имя таблицы перед «итоги»
запрос не вложенный, обычный единичный запрос.
виртуальных таблиц не создаю



0



2954 / 1766 / 82

Регистрация: 03.11.2011

Сообщений: 8,280

24.12.2012, 15:18

4

конструктор Вам в помощь. Уж запятую-то убрать — святое дело, но параметры вирт таблицы…

Не по теме:

Gokusa, Вы хоть чему-нибудь когда-нибудь…? Сколько можно на грабли поверхностного отношения наступать? В преферансе игрока, бездумно шлёпающего картами, раздевают мгновенно



0



Gokusa

Заблокирован

24.12.2012, 15:21

 [ТС]

5

народ, а что если программно отключить итоги и потом включить?
и как это сделать ?
наверное должно помочь.

Добавлено через 1 минуту
а конструктор итоги не делает, я не могу найти в конструкторе.
проще пальцыми написать.
так в чём ошибка — то , какая таблица ему нужна?



0



2954 / 1766 / 82

Регистрация: 03.11.2011

Сообщений: 8,280

24.12.2012, 15:25

6

Цитата
Сообщение от Gokusa
Посмотреть сообщение

проще пальцыми написать.

Видать не проще. Но если уж конструктор запроса у Вас итоги не делает…
Тогда слушайте внимательно: ИТОГИ здесь ни при чем. Запятая после алиаса причем.



0



Gokusa

Заблокирован

24.12.2012, 15:26

 [ТС]

7

а вот это вы неправы ))
если запятую уберу тогда будет «синтаксическая ошибка»:_))) на строке выше.
вот такие пироги.
з.ы.чукча не дурак но в покер играть не умеет.



0



2954 / 1766 / 82

Регистрация: 03.11.2011

Сообщений: 8,280

24.12.2012, 15:30

8

Тогда ждите. Придётся предоставлять Вам текст. В течение 10-15 мин (чукча занят, однако)

Добавлено через 38 секунд
Я ж намекнул на параметры вирт.т



0



Gokusa

Заблокирован

24.12.2012, 15:34

 [ТС]

9

ну с запятой-это я тупанул,
просто и без запятой пишет ошибку перед сумма(бла бла) в «итоги»
я думал мож в 1с какой-нить неподвластный логике синтаксис запросов.

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

Добавлено через 1 минуту
тока в том то и дело что как сумму параметр вирт табл.я представлять не хочу.



0



duk337

2954 / 1766 / 82

Регистрация: 03.11.2011

Сообщений: 8,280

24.12.2012, 15:38

10

1C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ
|   ПродажиОбороты.Номенклатура КАК Номенклатура,
|   ПродажиОбороты.КоличествоОборот КАК КоличествоОборот,
|   ПродажиОбороты.СтоимостьОборот КАК СтоимостьОборот
|ИЗ
|   РегистрНакопления.Продажи.Обороты(&Дат1, &Дат1, , Контрагент = &Контрагент) КАК ПродажиОбороты
|ИТОГИ
|   СУММА(КоличествоОборот),
|   СУММА(СтоимостьОборот)
|ПО
|   Номенклатура";
 
Запрос.УстановитьПараметр("", );
 
Результат = Запрос.Выполнить();
Выборка = Результат.Выбрать();
 
Пока Выборка.Следующий() Цикл
 
    
 
КонецЦикла;

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



0



Gokusa

Заблокирован

24.12.2012, 15:41

 [ТС]

11

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



0



2954 / 1766 / 82

Регистрация: 03.11.2011

Сообщений: 8,280

24.12.2012, 15:43

12

Цитата
Сообщение от Gokusa
Посмотреть сообщение

проще пальцыми написать.

В этом дело. В пальцах. Башку включи, гордыню умерь, и золотой ключик будет твой… после 3642-го ведра



0



Gokusa

Заблокирован

24.12.2012, 15:48

 [ТС]

13

спасибо за то что написали мне прикладное решение, толкьо прикладное мне не нужно.
мне нужно почему в моём запросе

1C
1
2
3
4
5
6
7
8
9
ВЫБРАТЬ
    ПродажиОбороты.Товар как товар,
    ПродажиОбороты.Склад,
    СУММА(ПродажиОбороты.КоличествоОборот) КАК КоличествоОборот
ИЗ
    РегистрНакопления.Продажи.Обороты КАК ПродажиОбороты
 
итоги
    по товар

чё ему надо.
а получить суммарное количество за период можно и вложеным запросом и наверняка ещё кучей способов- не в этом суть.
суть в том «херли ему надо перед «итоги «» ))) вот

Добавлено через 1 минуту
все равно не понимаю

1C
1
2
3
4
5
6
  РегистрНакопления.Продажи.Обороты(&Дат1, &Дат1, , Контрагент = &Контрагент) КАК ПродажиОбороты
|ИТОГИ
|   СУММА(КоличествоОборот),
|   СУММА(СтоимостьОборот)
|ПО
|   Номенклатура";

то же самое что у меня, почему тогда у меня ругается?

Добавлено через 2 минуты
допустим будет у меня другой регистр и не будет в нём периодов, и я хочу точно знать и быть увереным что поставлю итоги …. по …. и получу то что нужно.
когда нибудь может такой день и никогда и не настанет, так как я с 1с не работаю.
но я не понимаю чё ему надо перед «итоги» и я уже не уверен, у меня закрались сомнения в данном методе



0



2954 / 1766 / 82

Регистрация: 03.11.2011

Сообщений: 8,280

24.12.2012, 15:49

14

Цитата
Сообщение от Gokusa
Посмотреть сообщение

то же самое что у меня

Не… это не чукча. Ты попу от пальца отличаешь вообще?



0



Gokusa

Заблокирован

24.12.2012, 15:54

 [ТС]

15

ААААА я кажется понял в чем фишка- я это делал в отчёте если чё.
в отчете не работает.
не в отчете мой вариант тоже работает.
ответ на загадку был «писать запрос не в отчете»
)))

Добавлено через 1 минуту
отличаю, ну и че загнал три параметра в условие, и че ???
да хоть 333.это сути не меняет.
синтаксическая ошибка никуда не делась.я вот ставлю твой запрос и мне пишет бла бла бла пере сумма ()

Добавлено через 1 минуту
хошь я те принтскрин пришлю где твой запрос не работает )))
также как и мой, и ругается на ту же херню что и у меня?



0



2954 / 1766 / 82

Регистрация: 03.11.2011

Сообщений: 8,280

24.12.2012, 15:58

16

у тебя это функция ГРУППИРОВКИ
В отчете — СКД? Там вообще ничего не надо. В настройках всё.
Если обычное, тогда отключай построитель



0



Модератор

Эксперт 1С

3722 / 2917 / 574

Регистрация: 10.03.2011

Сообщений: 11,489

Записей в блоге: 1

24.12.2012, 15:58

17

const X=0, Y=5;

X=Y : X=5;

Я тоже самое пишу… Почему X=0 ????

Y=X : X=0;



0



2954 / 1766 / 82

Регистрация: 03.11.2011

Сообщений: 8,280

24.12.2012, 15:58

18

Но параметры врт.таблицы нужны



0



Dethmontt

24.12.2012, 16:00

Не по теме:

duk337, ну у тебя терпения вагон!!!



0



duk337

2954 / 1766 / 82

Регистрация: 03.11.2011

Сообщений: 8,280

24.12.2012, 16:01

20

Dethmontt, точно . Ещё подсказать, как исправить:

1C
1
Х<>0;



0



IT_Exp

Эксперт

87844 / 49110 / 22898

Регистрация: 17.06.2006

Сообщений: 92,604

24.12.2012, 16:01

20

Table1:
id | car1 | car2 | car3 | car4

**Table2:**
id | windows | doors | engines

I have this sql code:

sum(car1) + sum(car2) + sum(car3) + sum(car4) as 'tot_cars',
sum('doors') as 'tot_doors'
'tot_doors' - 'tot_cars' as 'door_rest'

I’ve tried this also and not working:

sum(car1) + sum(car2) + sum(car3) + sum(car4) as 'tot_cars',
sum('doors') as 'tot_doors'
('tot_doors' - 'tot_cars' as 'door_rest')

This:

sum(car1) + sum(car2) + sum(car3) + sum(car4) as 'tot_cars',
sum('doors') as 'tot_doors'
('tot_doors - tot_cars as door_rest')

And this:

sum(car1) + sum(car2) + sum(car3) + sum(car4) as 'tot_cars',
sum('doors') as 'tot_doors'
('tot_doors - tot_cars') as 'door_rest'

All not working.

Still I’m having errors in SQLSyntax, it said cannot find ‘door_rest‘ field in the database.

There are no problem with joining the two tables, because when I was querying the ‘tot_cars‘ it showed the data on my page. But I’m having trouble with the ‘door_rest‘ field.

Thank you for the help.

Для формирования и выполнения запросов к документам, справочникам, регистрам, журналам расчётов, планам счетов, бухгалтерским операциям и проводкам в системе используется специальный агрегатный тип данных — "Запрос". Возможности работы со справочниками, документами и журналами расчётов предоставляют достаточно мощные средства получения различной информации об этих объектах. Однако, существует также необходимость в получении информации, сгруппированной определённым образом, которую невозможно или очень сложно получить, непосредственно работая с документами, справочниками, регистрами или журналами расчётов. Для получения такой информации и существует механизм запросов.

Рассмотрим основные моменты работы с данным механизмом:

  • Контекст работы с запросами
  • Структура запросов и методика их использования
  • Атрибуты запросов
  • Методы запросов
  • Введение в язык запросов
  • Атрибуты, доступные при описании внутренних переменных
  • Правила объявления внутренних переменных
  • Операторы языка запросов
  • Примеры использования запросов
  • Способы оптимизации формирования отчётов

Контекст работы с запросами

Во всех программных модулях доступ к атрибутам и методам запросов может выполняться только через переменную со ссылкой на объект типа "Запрос", созданный с помощью функции СоздатьОбъект(). Чтобы вызвать атрибут или метод объекта, имя этого атрибута или метода пишется через точку после имени такой переменной.

При создании объекта типа "Запрос" в качестве параметра функции СоздатьОбъект() используется ключевое слово «Запрос» (англоязычный синоним — «Query»).

Запрос = СоздатьОбъект("Запрос");

Структура запросов и методика их использования

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

Запросы можно использовать не только для построения отчётов, но и для реализации других процедур конфигурации, требующих получения из базы данных некой сводной информации. Например, реализация алгоритма списания стоимости товара по методам FIFO или LIFO.

Работа с запросами предполагает следующий порядок:

  • при помощи функции СоздатьОбъект() создаётся объект типа "Запрос" и ссылка на него присваивается какой-либо переменной. Далее обращение к запросу производится посредством этой ссылки;
  • после создания переменной типа "Запрос" следует обращение к методу Выполнить(), которому в качестве параметра передаётся текст запроса, написанный на специальном языке запросов. Метод Выполнить() анализирует текст запроса, выполняет в соответствии с ним выборку данных и формирует временный выходной набор данных (выборку);
  • после этого организуется циклическая обработка сформированного временного набора данных (выборки) с целью получения требуемого отчёта.

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

НашЗапрос = СоздатьОбъект("Запрос");
ТекстЗапроса =
"//{{ЗАПРОС(Сформировать)
|СКЛАД = Регистр.ТоварныйЗапас.Склад;
|ТОВАР = Регистр.ТоварныйЗапас.Товар;
|КОЛИЧЕСТВО = Регистр.ТоварныйЗапас.Количество;
|Группировка ТОВАР Упорядочить По ТОВАР.Код;
|Группировка СКЛАД Упорядочить По СКЛАД.Код;
|Функция КОЛ = КонОст(КОЛИЧЕСТВО);
|"
;

Если НашЗапрос.Выполнить(ТекстЗапроса) = 0 Тогда
   Возврат;
КонецЕсли;

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

Структура временного набора данных

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

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

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

Продолжение примера:

 . . .
Пока НашЗапрос.Группировка("Товар") = 1 Цикл
   
    . . .
КонецЦикла;

 . . .

Поскольку после первого просмотра временного набора данных (как мы это сделали выше) объект НашЗапрос снова спозиционирован на первой записи, то можно запустить просмотр ещё раз.

Допустим, теперь нам надо просмотреть в цикле всю информацию по внешней (Товар) и вложенной группировке запроса (Склад). В теле цикла по внешней группировке (Товар) объект НашЗапрос позиционируется во временном наборе данных на записи, содержащие итоги по каждому конкретному товару, поэтому в теле этого цикла мы можем использовать итоги по товарам.

В теле цикла по вложенной группировке (Склад) объект НашЗапрос позиционируется во временном наборе данных на записи, содержащей строки по каждому конкретному товару на конкретном складе, поэтому в теле этого цикла мы можем использовать данные о количестве товара на складе.

После завершения цикла по вложенной группировке (Склад), объект НашЗапрос снова позиционируется на записи временного набора данных, где содержится общий итог по конкретному товару. Поэтому, общие итоги по конкретному товару можно использовать в двух местах: до и после цикла по вложенной группировке (Склад).

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

Продолжение примера:

 . . .
Пока НашЗапрос.Группировка("Товар") = 1 Цикл
   
    . . .
   Пока НашЗапрос.Группировка("Склад") = 1 Цикл
      
       . . .
   КонецЦикла;
   
    . . .
КонецЦикла;

 . . .

После выхода из процедуры, где была определена переменная, содержащая объект типа "Запрос" (в нашем примере НашЗапрос) или после уничтожения объекта типа "Запрос" (Наш3апрос = 0;), временный набор данных на локальной машине пользователя уничтожается.

Из приведенного выше примера можно сделать несколько важных заключений:

  • при просмотре временного набора данных, вложенность циклов просмотра должна точно повторять порядок группировок запроса (нельзя входить во вложенную группировку, не войдя в предыдущую);
  • допускается просматривать временный набор данных, опуская с некоторого уровня все вложенные (внутренние) группировки;
  • не следует прерывать последовательность просмотра временного набора данных (например, оператором Прервать), если вы собираетесь использовать временный набор дальше или ещё раз, так как в таком случае теряется точка позиционирования во временном наборе и продолжать просмотр невозможно.

Примера обработки запроса:

Пока Запрос.Группировка("Товар") = 1 Цикл
   Если (Запрос.Товар = НужныйТовар) Тогда
      Пока Запрос.Группировка("Отдел") = 1 Цикл
         Если (Запрос.Отдел = НужныйОтдел) Тогда
            Пока Запрос.Группировка("Сотрудник") = 1 Цикл
               Если (Запрос.Сотрудник = НужныйСотрудник) Тогда
                  Пока Запрос.Группировка("Док") = 1 Цикл
                     Док = Запрос.Док;
                     Если Запрос.ПрихКол <> 0 Тогда
                        Таб.ВывестиСекцию("Приход");
                     ИначеЕсли Запрос.РасхКол <> 0 Тогда
                        Приращение = Запрос.РасхКол;
                        Таб.ВывестиСекцию("Расход");
                     КонецЕсли;
                  КонецЦикла;
               КонецЕсли;
            КонецЦикла;
         КонецЕсли;
      КонецЦикла;
   КонецЕсли;
КонецЦикла;

Атрибуты запросов

Атрибутами запроса являются объявленные в описании запроса внутренние переменные (см. далее описание языка запросов), имена группировок и функций запроса. Все атрибуты запросов — только для чтения. Чтобы обратиться к атрибуту запроса, имя этого атрибута пишется через точку после имени ссылки на запрос. Значения атрибутов запроса определяются текущим положением в полученной выборке.

Методы запросов

Выполнить запрос позволяет метод Выполнить() (англоязычный синоним — Execute()). Он анализирует описание, содержащееся в тексте запроса, выполняет выборку данных, формирует временный выходной набор данных (выборку) и вычисляет значения функций запроса. Возвращаемым значением метода является число 1, если запрос выполнен успешно, или 0, если зафиксирована ошибка при выполнении запроса (синтаксическая или времени выполнения).

Синтаксис метода:

Выполнить(<ТекстЗапроса>)

где <ТекстЗапроса> — строковое выражение, содержащее текст запроса на языке запросов.

Пример использования:

Процедура Сформировать()
   
   ЖР = СоздатьОбъект("ЖурналРасчетов.Зарплата");
   _Дата = ЖР.НачалоТекущегоПериода();
   
   Запрос = СоздатьОбъект("Запрос");
   ЗапросКат = СоздатьОбъект("Запрос");
   флаг1 = Запрос.Выполнить(
   "//({ЗАПРОС(Двойной)
   |Период с _Дата по _Дата;
   |Оклад = Справочник.Сотрудники.Оклад;
   |Пдр = Справочник.Сотрудники.МестоРаботы.Владелец;
   |Ктг = Справочник.Сотрудники.Категория;
   |Условие((Ктг.Выбран() = 1) И (Пдр.Выбран() = 1));
   |Группировка Пдр без групп;
   |Группировка Ктг без групп;
   |Функция Всего = Сумма(Оклад);
   |"
   );
   Флаг2 = ЗапросКат.Выполнить(
   "//{{ЗАПРОС(Одинарный)
   |Период с _Дата по _Дата;
   |Оклад = Справочник.Сотрудники.Оклад;
   |Ктг = Справочник.Сотрудники.Категория;
   |Условие(Ктг.Выбран() = 1);
   |Группировка Ктг без групп;
   |Функция Всего = Сумма(Оклад);
   |"
   );
   
   Если ((Флаг1 = 0) ИЛИ (Флаг2 = 0)) Тогда
      Сообщить("Ошибка в запросе!");
      Возврат;
   КонецЕсли;
   
   Таб = СоздатьОбъект("Таблица");
   
   Таб.ВывестиСекцию("Документ<|ДокументВерт<");
   Пока ЗапросКат.Группировка("Ктг") = 1 Цикл
      Таб.ПрисоединитьСекцию("Документ<|Осн2");
   КонецЦикла;
   Таб.ПрисоединитьСекцию("Документ<|ДокументВерт>");
   
   Таб.ВывестиСекцию("КолонТитул|ДокументВерт<");
   Пока ЗапросКат.Группировка("Ктг") = 1 Цикл
      Таб.ПрисоединитьСекцию("КолонТитул|Осн2");
   КонецЦикла;
   Таб.ПрисоединитьСекцию("КолонТитул|ДокументВерт>");
   Продолжать = 1;
   Пока Запрос.Группировка("Пдр") = 1 Цикл
      
      Таб.ВывестиСекцию("Осн1|ДокументВерт<");
      Далее = 1;
      Пока Продолжать = 1 Цикл
         
         СлКат = ЗапросКат.Группировка("Ктг");
         Если Далее = 1 Тогда
            ОК = Запрос.Группировка("Ктг");
         КонецЕсли;
         Если СлКат = 0 Тогда
            Прервать;
         КонецЕсли;
         Если ЗапросКат.Ктг = Запрос.Ктг Тогда
            Таб.ПрисоединитьСекцию("Осн1|Осн2");
            Далее = 1;
         Иначе
            Таб.ПрисоединитьСекцию("Осн1|Пусто");
            Далее = 0;
         КонецЕсли;
      КонецЦикла;
      Таб.ПрисоединитьСекцию("Осн1|ДокументВерт>");
   КонецЦикла;
   
   Таб.ВывестиСекцию("Документ>|ДокументВерт<");
   Пока ЗапросКат.Группировка("Ктг") = 1 Цикл
      Таб.ПрисоединитьСекцию("Документ>|Осн2");
   КонецЦикла;
   Таб.ПрисоединитьСекцию("Документ>|ДокументВерт>");
   
   Таб.Опции(0, 0, 0, 0);
   Таб.ТолькоПросмотр(1);
   Таб.Показать("Результат", );
КонецПроцедуры

Установить режим использования графы отбора в запросе позволяет метод ИспользоватьГрафуОтбора() (англоязычный синоним — UseSelectionColumn()). Если метод не используется — по умолчанию устанавливается автоматический выбор графы отбора. Возвращаемым значением метода является строковое значение — идентификатор использованной реально графы отбора, если метод вызывается после выполнения запроса.

Синтаксис метода:

ИспользоватьГрафуОтбора(<ГрафаОтбора>)

где <ГрафаОтбора> — строковое выражение — идентификатор графы отбора, как он задан в Конфигураторе. Данный параметр устанавливает режим использования определённой графы отбора. Возможными значениями параметра также являются:

  • "*" — автоматический выбор графы отбора;
  • "" (пустая строка) — не использовать графу отбора.

Пример использования:

Запрос = СоздатьОбъект("Запрос");
ТекстЗапроса =
"//{{ЗАПРОС(ОбработкаДок)
|Период с '01.10.96' по '05.10.96';
|ОбрабатыватьДокументы Все;
|Тов = Документ.РасхНакл.Товар;
|Клиент = Документ.РасхНакл.Клиент;
|Группировка Клиент;
|Группировка Тов;
|Группировка Документ;
|"
;

Запрос.ИспользоватьГрафуОтбора("Клиент");
Если Запрос.Выполнить(ТекстЗапроса) = 0 Тогда
   Возврат;
КонецЕсли;

Организовать цикла получения данных из выборки, сформированной в результате работы метода Выполнить(), позволяет метод Группировка() (англоязычный синоним — Group()). Метод позиционирует в выборке очередную строку в порядке, определённом параметром <Группировка>. Нельзя использовать метод Группировка(), задавая в качестве параметра младшие группировки, не использовав предварительно этот метод для позиционирования по старшим группировкам. Старшинство группировок определяется порядком их следования в тексте запроса.

Синтаксис метода:

Группировка(<Группировка>, <Направление>)

где

  • <Группировка> — выражение, содержащее порядковый номер или имя группировки;
  • <Направление> — необязательный параметр — числовое выражение, определяющее направление выборки. Возможные значения:
    • 1 — выборка значений группировки по возрастанию (значение по умолчанию);
    • -1 (минус единица) — выборка значений группировки по убыванию.

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

Пример использования:

Процедура Сформировать()
   Перем Запрос, ТекстЗапроса;
   Если (Число(ДатаНач) = 0) ИЛИ (Число(ДатаКон) = 0) Тогда
      Предупреждение("Не задан период!");
      Возврат;
   КонецЕсли;
   
   Запрос = СоздатьОбъект("Запрос");
   ТекстЗапроса =
   "//{{ЗАПРОС(Сформировать)
   |с ДатаНач по ДатаКон;
   |Рез = ЖурналРасчетов.Зарплата.Результат;
   |Сотр = ЖурналРасчетов.Зарплата.Объект;
   |Группировка Сотр без групп;
   |Группировка ПериодЖурнала;
   |Функция Сум = Сумма(Рез);
   |"
   ;
   Если Сотрудник.Выбран() = 1 Тогда
      ТекстЗапроса = ТекстЗапроса + "Условие(Сотр = Сотрудник);";
   КонецЕсли;
   
   Если Запрос.Выполнить(ТекстЗапроса) = 0 Тогда
      Возврат;
   КонецЕсли;
   
   Таб = СоздатьОбъект("Таблица");
   
   Пока Запрос.Группировка("Сотр") = 1 Цикл
      
      Таб.ВывестиСекцию("Сотр<");
      Пока Запрос.Группировка("ПериодЖурнала") = 1 Цикл
         
         Таб.ВывестиСекцию("Мес");
      КонецЦикла;
      Таб.ВывестиСекцию("Сотр>");
   КонецЦикла;
   
   Таб.Опции(0, 0, 0, 0);
   Таб.ТолькоПросмотр(1);
   Таб.Показать("Результат", );
КонецПроцедуры

Выделить строки временного набора данных, которые являются группой справочника, позволяет метод ЭтоГруппа() (англоязычный синоним — IsItAGroup()). Возвращаемым значением метода является число 1, если текущая строка выборки (временного набора данных, сформированного в результате выполнения запроса) является группой справочника, или 0, если это обычный элемент справочника.

Синтаксис метода:

ЭтоГруппа(<ИмяГруппировки>)

где <ИмяГруппировки> — выражение, содержащее порядковый номер или имя группировки.

Пример использования:

Пока (Запр.Группировка("Товар") = 1) И (Запр.ЭтоГруппа("Товар") = 0) Цикл
    . . .
КонецЦикла;

Получить дату начала периода запроса позволяет метод НачалоПериода() (англоязычный синоним — BeginOfPeriod()). Если в тексте запроса указана одна из предопределённых группировок типа период ("Год", "Месяц", "День" и т.д.), то при обработке этой и вложенных в неё группировок метод НачалоПериода() будет возвращать начало периодов текущих значений этих группировок. Параметры у метода отсутствуют.

Пример использования:

ДатаНачала = Запрос.НачалоПериода();

Получить дату конца периода запроса позволяет метод КонецПериода() (англоязычный синоним — EndOfPeriod()). Если в тексте запроса указана одна из предопределённых группировок типа период ("Год", "Месяц", "День" и т.д.), то при обработке этой и вложенных в неё группировок метод КонецПериода() будет возвращать конец периодов текущих значений этих группировок. Параметры у метода отсутствуют.

Пример использования:

ДатаКонца = Запрос.КонецПериода();

Осуществить прямое позиционирование на запись в выборке по конкретным значениям группировок позволяет метод Получить() (англоязычный синоним — Get()). Количество параметров метода зависит от количества группировок в запросе. Можно пропускать значения одной или нескольких последних группировок, в этом случае метод позиционируется на запись, которая будет содержать итоговые значения для указанных группировок. Пропускаемые при вызове метода последние значения группировок должны заменяться запятыми. Если при вызове метода опущены все параметры, то выборка позиционируется на самое начало временного набора данных, на строку итогов. Возвращаемым значением метода является число 1, если запись найдена, или 0 – если нет.

После выполнения метода Получить() может осуществляться дальнейший обход выборки вызовами метода Группировка().

Синтаксис метода:

Получить(<ЗначениеГруппировки1>, ..., <ЗначениеГруппировкиN>)

где <ЗначениеГруппировки1>,, <ЗначениеГруппировкиN> — выражения, содержащие значения группировок запроса.

Пример использования:

Текст3апроса = "
| ...
|Группировка Должность;
|Группировка Категория;
| ...
|";

Если Запрос.Выполнить(ТекстЗапроса) = 0 Тогда
   Возврат;
КонецЕсли;
Если Запрос.Получить(ВыбДолжн, ВыбКатег) = 0 Тогда
   Если Запрос.Получить(ВыбДолжн, ) = 0 Тогда
       . . .
   КонецЕсли;
КонецЕсли;

Осуществить прямое позиционирование на начало выборки позволяет метод ВНачалоВыборки() (англоязычный синоним — ToSelectionBegin()). Например, если необходимо перейти на верхний уровень группировок, чтобы затем организовать проход группировки первого уровня (в любом направлении), следует использовать метод ВНачалоВыборки(). Возвращаемым значением метода является число 1, если операция выполнена успешно, или 0 – если нет. Параметры у метода отсутствуют.

Пример использования:

Текст3апроса = "
| ...
|Группировка Должность;
|Группировка Категория;
| ...
|";

Если Запрос.Выполнить(ТекстЗапроса) = 0 Тогда
   Возврат;
КонецЕсли;
Если Запрос.Получить(ВыбДолжн, ВыбКатег) = 0 Тогда
   Если Запрос.Получить(ВыбДолжн, ) = 0 Тогда
       . . .
   КонецЕсли;
КонецЕсли;
Запрос.ВНачалоВыборки();
Пока Запрос.Группировка(1, -1) Цикл
    . . .
КонецЦикла;

Получить значение поля упорядочивания из временной выборки запроса, не обращаясь к базе данных, позволяет метод ЗначениеУпорядочивания() (англоязычный синоним — OrderValue()).

Примечание: Если в тексте запроса для данной группировки не используется конструкция "Упорядочить по", то в этом случае действует упорядочивание по умолчанию:

  • для справочников — зависит от основного представления при описании справочника в Конфигураторе (код или наименование);
  • для документов — дата и время создания документа.

Синтаксис метода:

ЗначениеУпорядочивания(<Группировка>, <Упорядочив>)

где

  • <Группировка> — выражение, содержащее значение номера или имени группировки (номер работает быстрее);
  • <Упорядочив> — необязательный параметр. Порядковый номер параметра упорядочивания указанной группировки. Значение по умолчанию — 1.

Пример использования:

Текст3апроса = "
|ВидРаб = Документ.Наряд.ВидРаботы;
|Сотр = Документ.Наряд.Сотрудник;
|Группировка ВидРаб
|Упорядочить По ВидРаб.Код, ВидРаб.Стоимость;
|Группировка Сотр;
|";
 . . .

Запрос.ЗначениеУпорядочивания("ВидРаб", 2);

Запрос.ЗначениеУпорядочивания(2, 1);

Получить значение атрибута запроса по его имени позволяет метод ПолучитьАтрибут() (англоязычный синоним — SetAttrib()).

Синтаксис метода:

ПолучитьАтрибут(<ИмяАтрибута>)

где <ИмяАтрибута> — строковое выражение, содержащее имя любого атрибута запроса.

Пример использования:

Текст3апроса = "
|ВидРаб = Документ.Наряд.ВидРаботы;
|Сотр = Документ.Наряд.Сотрудник;
|Группировка ВидРаб
|Упорядочить По ВидРаб.Код, ВидРаб.Стоимость;
|Группировка Сотр;
|";
 . . .

Запрос.ПолучитьАтрибут("ВидРаб");

Запрос.ПолучитьАтрибут("Сотр");

Выгрузить результаты запроса в указанную таблицу значений позволяет метод Выгрузить() (англоязычный синоним — Unload()). Возвращаемым значением метода является число 1, если выгрузка произошла успешно, иначе – 0.

Синтаксис метода:

Выгрузить(<ТаблЗнач>, <Флаг>, <Итоги>)

где

  • <ТаблЗнач> — таблица значений, куда выгружаются результаты запроса;
  • <Флаг> — необязательный параметр. Число:
    • 0 — значения групп и функций (значение по умолчанию);
    • 1 — значения групп и функций, дополнительных переменных;
    • 2 — значения упорядочиваний групп и функций;
    • 3 — значения упорядочиваний групп и функций, дополнительных переменных;

    или строка типа "Товар(1), Товар(2), Товар, Склад, Приход, Расход", где Товар(1) — значение первого упорядочивания группировки "Товар" и т.д.

  • <Итоги> — необязательный параметр. Число:
    • 0 — итоги по группировкам не выводить;
    • 1 — итоги по группировкам выводить сверху (значение по умолчанию);
    • 2 — итоги по группировкам выводить снизу;
    • 3 — итоги по группировкам выводить сверху и снизу.

Пример использования:

Текст3апроса = "
| ...
|Группировка Должность;
|Группировка Категория;
| ...
|";

Если Запрос.Выполнить(ТекстЗапроса) = 0 Тогда
   Возврат;
КонецЕсли;
ТаблЗнач = Создать("ТаблицаЗначений");
Запрос.Выгрузить(ТаблЗнач, 0, 0);

Введение в язык запросов

Язык запросов предназначен для описания запросов к документам, справочникам, регистрам, журналам расчётов, планам счетов, бухгалтерским операциям и проводкам. Текст описания запроса передается методу Выполнить() в качестве параметра. В результате выполнения этого метода генерируется временный выходной набор данных, который в дальнейшем используется для заполнения формы отчёта.

Формат текста описания запроса

Текст описания запроса на языке запросов состоит из последовательности операторов. Концом оператора является символ «;» (точка с запятой). Операторы могут записываться в любом порядке, однако, следует помнить, что интерпретатор языка запросов однопроходный, следовательно, сначала следует описать переменную, и только потом её использовать в операторах Группировка, Функция или Условие.

Пример:

Текст3апроса =
"//({ЗАПРОС(РасчЛистки)
|  // Задаем интервал запроса
|Период с ДатаНач по ДатаКон;
|  // Определяем внутренние переменные
|Рез = ЖурналРасчетов.Зарплата.Результат;
|Расч = ЖурналРасчетов.Зарплата.ВидРасч;
|Дни = ЖурналРасчетов.Зарплата.Дни;
|Сотр = ЖурналРасчетов.Зарплата.Объект;
|  // Назначаем группировки
|Группировка Сотр без групп;
|Группировка Расч;
|  // Назначаем функции
|Функция Сум = Сумма(Рез);
|Функция Дней = Сумма(Дни);
|  // Назначаем условие
|Условие(Рез <> 0);
|"
;
 . . .

Как видно из вышеприведённого примера, в тексте запроса, также как и в остальном программном коде, допускается использование комментариев. Комментарий в тексте описания запроса начинается парой символов слэша (//) и заканчивается концом строки.

Соглашения и обозначения, используемые при описании языка

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

  • [] — в квадратные скобки заключаются необязательные синтаксические элементы;
  • []+ — в квадратные скобки со знаком «+» заключаются обязательные синтаксические элементы, которые могут использоваться один или более раз;
  • []* — в квадратные скобки со знаком «*» заключаются необязательные синтаксические элементы, которые могут использоваться один или более раз;
  • () — круглые скобки заключают в себе список параметров;
  • | — вертикальной линией разделяются синтаксические элементы, среди которых нужно выбирать один и только один.

Зарезервированные слова языка запросов

Ключевые слова — это слова, которые используются в языке запросов для обозначения встроенных операторов. Приведённые далее ключевые слова являются зарезервированными и не могут использоваться в качестве имён внутренних переменных описания запросов. Каждое ключевое слово имеет два представления — русское и английское. Английское представление является традиционным для языков программирования. Ключевые слова в русском и английском представлении могут свободно смешиваться в одном исходном тексте. Регистр букв ключевых слов не имеет значения, то есть они могут быть набраны в любом регистре, например: Функция, ФУНКЦИЯ, фУНКЦИЯ.

Ниже приведен полный список зарезервированных слов языка запросов в обоих представлениях:

  • Без (Without)
  • Год (Year)
  • Групп (Groups)
  • Группировка (Group)
  • День (Day)
  • Документ (Document)
  • И (And)
  • ИЛИ (Or)
  • Квартал (Quarter)
  • Когда (When)
  • Месяц (Month)
  • Неделя (Week)
  • НомерСтроки (LineNum)
  • Обрабатывать (Process)
  • ОбрабатыватьДокументы (ProcessDocuments)
  • ОбрабатыватьОперации (PrосessOperations)
  • Период (Period)
  • ПериодЖурнала (JournalPeriod)
  • По (By)
  • По (Till)
  • С (From)
  • СтрокаДокумента (DocumentLine)
  • Упорядочить (Order)
  • Условие (Condition)
  • Функция (Function)

Использование констант

В тексте запроса, также как и в остальном программном коде, допускается использование числовых и строковых констант (литералов), а также констант типа "Дата".

Числовая константа описывается следующей синтаксической диаграммой:

[+|-][0-9]+ | [0-9]*.[0-9]+

Пример числовых констант:

-17
43.712
.43842

Строковая константа — это строка, заключенная в двойные кавычки. Она не может быть многострочной.

Пример строковой константы:

"Это текстовая константа"

Константа типа "Дата" задаётся в виде строки, заключённой в одинарные кавычки, в формате 'ДД.ММ.ГГ' или 'ДД.ММ.ГГГГ'.

Примеры констант типа "Дата":

'21.05.96'
'25.09.1964'

Внутренние переменные

Внутренние переменные — это переменные, объявленные в тексте описания запроса. Именем переменной может быть любая последовательность букв, цифр и символов подчёркивания (_), начинающаяся с буквы или знака подчёркивания. Имена внутренних переменных не должны совпадать с зарезервированными словами языка запросов. Распознавание имён переменных, названий операторов, процедур и функций ведётся без учёта регистра букв.

Примеры имён переменных:

_43842
НачПериода

Примеры использования переменных:

Сотр = НовЗапрос.Сотр;
Кат = НовЗапрос.Кат;
ИТОГ = НовЗапрос.Итого;

Конкретизация переменной

Конкретизация переменной — это уточнение описания внутренней переменной, если это возможно в текущем контексте. Конкретизации переменной могут использоваться в языке запросов в операторах Группировка ... Упорядочить По и в качестве аргумента оператора Функция.

Синтаксис:

<ВнутренняяПеременная>[.<Путь>]+

где

  • <ВнутренняяПеременная> — идентификатор объявленной ранее внутренней переменной;
  • <Путь> — доступный атрибут внутренней переменной или конкретизации переменной (см. ниже «Атрибуты, доступные при описании внутренних переменных»).

Пример использования:

Запрос = СоздатьОбъект("Запрос");
ТекстЗапроса =
" //{{ЗАПРОС(ОбработкаДок)
|Период с '01.10.96' по '05.10.96';
|ОбрабатыватьДокументы Все;
|Тов = Справочник.Товары.ТекущийЭлемент, Документ.РасхНакл.Товар;
|  // используем конкретизацию внутренней переменной Тов
|Группировка Тов Упорядочить По Тов.Наименование;
|Группировка Документ;
|Группировка СтрокаДокумента;
|"
;

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

Внимание! Запрос не манипулирует величинами типа "Строка неограниченной длины".

Внешние переменные

Внешние переменные — это переменные из области видимости процедуры или функции программного модуля, в теле которого используется данный запрос. Внешние переменные в тексте описания запроса могут использоваться в операторах Период с и Условие.

Пример использования:

Перем ДатаНач, ДатаКон;

Процедура Сформировать()
   Если (Число(ДатаНач) = 0) ИЛИ (Число(ДатаКон) = 0) Тогда
      Предупреждение("Не задан период!");
      Возврат;
   КонецЕсли;
   
   Запрос = СоздатьОбъект("Запрос");
   ТекстЗапроса =
   "//{{ЗАПРОС(Сформировать)
   |  // используем внешние переменные ДатаНач и ДатаКон
   |с ДатаНач по ДатаКон;
   |Рез = ЖурналРасчетов.Зарплата.Результат;
   |Сотр = ЖурналРасчетов.Зарплата.Объект;
   |Группировка Сотр без групп;
   |Группировка ПериодЖурнала;
   |Функция Сум = Сумма(Рез);
   |"
   ;
   
   Если ВыбСотр.Выбран() = 1 Тогда
      ТекстЗапроса = ТекстЗапроса + "Условие(Сотр = ВыбСотр);";
   КонецЕсли;
   
   Если Запрос.Выполнить(ТекстЗапр) = 0 Тогда
      Возврат;
   КонецЕсли;
    . . .
КонецПроцедуры

Атрибуты, доступные при описании внутренних переменных

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

  • Документ (Document) — данные документов;
  • Справочник (Reference) — данные справочников;
  • Регистр (Register) — данные регистров;
  • ЖурналРасчетов (CalcJournal) — данные журналов расчёта;
  • Счет (Account) — данные счетов;
  • Операция (Operation) — данные бухгалтерских операций и проводок.

Эти названия являются первыми в пути описания переменных. В качестве атрибутов допускается использовать любые реквизиты, которые заданы для них в Конфигураторе в дереве метаданных (реквизиты для справочников, документов и журналов расчётов; измерения и ресурсы для регистров). Кроме этих атрибутов, разрешён так же доступ к следующим предопределённым атрибутам:

  • Доступные атрибуты объектов типа "Документ":
    • ВремяДок (DocTime) — время документа;
    • ДатаДок (DocDate) — дата документа;
    • НомерДок (DocNum) — номер документа;
    • НомерСтроки (LineNum) — номер строки документа;
    • ТекущийДокумент (CurDocument) — значение текущего документа.
  • Доступные атрибуты объектов типа "Справочник":
    • Родитель (Parent) — родитель элемента многоуровневого справочника;
    • Владелец (Owner) — владелец подчиненного справочника;
    • Код (Code) — код элемента справочника;
    • Наименование (Description) — наименование элемента справочника;
    • ТекущийЭлемент (CurItem) — значение текущего элемента справочника.
  • Доступные атрибуты объектов типа "Регистр":
    • НомерСтроки (LineNum) — номер строки документа, выполнившего движение регистра (в случае, когда в Модулях документов в конфигурации перед движением регистра использовали метод ПривязыватьСтроку);
    • ТекущийДокумент (CurDocument) — значение документа, выполнившего движение регистра.
  • Доступные атрибуты объектов типа "ПланСчетов":
    • БезКорреспонденций (IsSingle) — флаг того, что элемент плана счетов — забалансовый;
    • Валютный (IsCurrency) — флаг валютного учёта элемента плана счетов;
    • Код (Code) — код элемента плана счетов;
    • Количественный (IsAmount) — флаг количественного учёта элемента плана счетов;
    • Наименование (Description) — наименование элемента плана счетов;
    • ТекущийСчет (CurAccount) — значение текущего счета плана счетов.
  • Доступные атрибуты объектов типа "Операция":
    • ВремяОперации (OperTime) — время операции;
    • ДатаОперации (OperDate) — дата операции;
    • Содержание (Description) — содержание операции;
    • СуммаОперации (OperSum) — сумма операции;
    • ТекущийДокумент (CurDocument — значение документа создавшего операцию.
  • Доступные атрибуты объектов типа "Проводка":
    • ВалСумма (CurSum) — валютная сумма проводки (для счетов с валютным учётом);
    • Валюта (Currency) — валюта проводки;
    • Количество (Amount) — количество проводки (для счетов с количественным учётом);
    • КорСчет (CorAccount) — корреспондирующий счёт. Корреспондирующим счетом, для которого является Счет;
    • Сумма (Sum) — сумма проводки;
    • Счет (Account) — счет, для обработки корреспонденции. Корреспондирующим счётом, для которого является КорСчет.

Примеры использования атрибутов:

Запрос = СоздатьОбъект("Запрос");
ТекстЗапроса =
" //{{ЗАПРОС(Сформировать)
|Период с НачДата по КонДата;
|ДОКУМ = Документ.РасходнаяБН.ТекущийДокумент,
|   Документ.РасходнаяКредит.ТекущийДокумент,
|   Документ.РасходнаяНал.ТекущийДокумент,
|   Документ.РасходнаяРеализ.ТекущийДокумент,
|   Документ.Счет.ТекущийДокумент;
|Группировка ДОКУМ; //по документам
|"
;
Запрос = СоздатьОбъект("Запрос");
ТекстЗапроса =
"//{{ЗАПРОС(Печать)
|Товар = Справочник.Товары.ТекущийЭлемент;
|Группировка Товар Упорядочить по Товар.МинЗапас;
|"
;
Запрос = СоздатьОбъект("Запрос");
ТекстЗапроса =
"//{{ЗАПРОС(Сформировать)
|Период с НачДата по КонДата;
|ВидТоплива = Регистр.ПокупателиКолво.ВидыТоплива;
|Вес = Регистр.ПокупателиКолво.Кг;
|Покуп = Регистр.ПокупателиКолво.Покупатели;
|Док = Регистр.ПокупателиКолво.ТекущийДокумент;
|Ном = Регистр.ПокупателиКолво.НомерСтроки;
|Группировка ВидТоплива; //по измерению Регистра
|Группировка Док; // по документам, двигавшим Регистр
|Группировка Ном; // по номерам строк документов
|Функция ВсегоКолво = КонОст(Вес);
|Функция ПриходКолво = Приход(Вес);
|Условие(Покуп = ВыбПокупатель);
|"
;

Правила объявления внутренних переменных

Внутренние переменные используются в тексте запроса для образования ссылок на объекты конфигурации, чтобы использовать их при построении таких операторов запроса, как Группировка, Функция, Условие.

Синтаксис объявления внутренней переменной:

<ИмяПеременной> = <ОписаниеПеременной> [, <ОписаниеПеременной>]+;

где

  • <ИмяПеременной> — имя объявляемой внутренней переменной описания запроса;
  • <ОписаниеПеременной> — ссылка, указывающая на доступный в языке запросов атрибут документа, справочника, регистра или журнала расчётов (см. выше «Атрибуты, доступные при описании внутренних переменных»).

В объявлении внутренней переменной можно указывать несколько вариантов описания переменной. Все описания должны указывать на один и тот же тип данных (число, строку, справочник или документ). Переменной, указывающей на разные справочники или документы, присваивается тип данных "Справочник неопределённого вида" или "Документ неопределённого вида" соответственно.

Например, можно определить внутреннюю переменную:

Товар = Документ.Перемещение.Товар, Документ.Расходная.Товар;

и использовать её для создания группировки. Такой состав внутренней переменной как бы дает группировке задание — просмотреть все документы видов Перемещение и Расходная и выбрать все товары, встречающиеся либо в документах вида Перемещение, либо в документах Расходная.

Еще пример. Допустим, у нас есть регистр Взаиморасчеты и регистр Кредиты, и в том и в другом есть измерение Клиент. Определяем внутреннюю переменную:

Должник = Регистр.Взаиморасчеты.Клиент, Регистр.Кредиты.Клиент;

Если использовать такую внутреннюю переменную для образования группировки, то она будет означать следующее: пройти по регистру Взаиморасчеты и по регистру Кредиты, вычислить заданные в запросе функции и выбрать значения клиентов, для которых значения хотя бы одной функции будет ненулевой. Здесь мы видим, что формирование запроса по регистрам имеет некоторые особенности (обязательно наличие функций, причём их вычисленные значения должны быть отличны от нуля, только в этом случае найденные объекты включаются во временный набор данных формируемый запросом).

Внимание! Если при описании внутренней переменной указать на разные типы данных, например, на "Справочник" и на "Документ", то это просто вызовет сообщение об ошибке. Например, следующее определение внутренней переменной будет ошибочным:

ААА = Справочник.Товары.ТекущийЭлемент, Документ.Счет.ТекущийДокумент;   

Однако допускается в описании внутренней переменной указание на разные справочники либо на разные документы. Переменной, указывающей на разные справочники или документы, присваивается тип данных "Справочник неопределённого вида" или "Документ неопределённого вида" соответственно. Например, правомерно задать такую внутреннюю переменную:

Парам = Документ.Счет.Клиент, Документ.Счет.Фирма;

(Здесь предполагается, что в контексте конфигурации, реквизиты Клиент и Фирма — это элементы справочников). Если использовать такую внутреннюю переменную для построения группировки, то она будет означать следующее: пройти по документам Счет и выбрать значения клиентов и фирм, встречающихся в них (и, например, упорядочить эти элементы по наименованию). Как интерпретировать результаты полученной выборки при таком запросе — будет зависеть от контекста поставленной задачи.

Особенности описания внутренних переменных для типов "Операция" и "Проводка"

В языке запросов описание внутренних переменных для агрегатных типов данных типа "Операция" и "Проводка" начинается со слова «Операция» вне зависимости от того, будет ли обращение к бухгалтерским операциям или к проводкам. Описание переменной определяется следующим образом:

Операция.(
   <Реквизиты0перации>
   |  <ПредРеквОпераций>
   |  <РеквизитыПроводок>
   |  <ПредРеквПроводок>
   |  Дебет. ( Счет | <Субконто> )
   |  Кредит. ( Счет | <Су6конто> )
   |  Субконто.<ВидСубконто>
   |  КорСубконто.<ВидСубконто>
)

где

  • <Реквизиты0перации> — реквизиты операции, объявленные в метаданных;
  • <ПредРеквОпераций> — предопределённые реквизиты операций;
  • <РеквизитыПроводок> — реквизиты проводок, объявленные в метаданных;
  • <ПредРеквПроводок> — предопределённые реквизиты проводок;
  • <ВидСубконто> — идентификатор вида субконто.

Применение слов «Дебет», «Кредит» в описании переменных позволяют оперировать дебетовой и кредитовой частями проводки, такими как счёт и вид субконто. Применение слов «Субконто» и «КорСубконто» в описании переменных позволяют оперировать как субконто, так и корреспондирующим субконто.

Пример:

Сум = Операция.Сумма;
Сч = Операция.Дебет.Счет, Операция.Кредит.Счет;

О дополнительных именах доступа

Несколько слов о дополнительных именах доступа к стандартной информации, которые определены в языке запросов. Речь идёт о конструкции ТекущийЭлемент для справочников и ТекущийДокумент для документов и регистров (не надо путать эти конструкции языка запросов с одноимёнными методами встроенного языка, хотя их смысл во многом совпадает).

Для справочников использование конструкции ТекущийЭлемент в описании внутренней переменной означает выборку элемента справочника как такового (целиком всей записи справочника).

Аналогично при работе с документами, использование конструкции ТекущийДокумент в описании внутренней переменной, означает выборку документа как такового (целиком всего документа как объекта конфигурации). Сравните два примера, приведённых ниже.

Пример 1. Здесь нас интересуют товары, встречающиеся в документах:

ТОВАР = Документ.РасходнаяБН.Товар, 
   Документ.РасходнаяКредит.Товар,
   Документ.РасходнаяНал.Товар,
   Документ.РасходнаяРеализ.Товар,
   Документ.Счет.Товар;

Пример 2. Здесь нас интересуют сами документы указанных видов как таковые:

ДОКУМ = Документ.РасходнаяБН.ТекущийДокумент, 
   Документ.РасходнаяКредит.ТекущийДокумент,
   Документ.РасходнаяНал.ТекущийДокумент,
   Документ.РасходнаяРеализ.ТекущийДокумент,
   Документ.Счет.ТекущийДокумект;

Использование для документов конструкции НомерСтроки в описании внутренней переменной, означает выборку номеров строк документов (не самих строк, а чисел, обозначающих номера строк в документе):

СТРОКА = Документ.РасходнаяБН.НомерСтроки;

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

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

Пример:

Запрос = СоздатьОбъект("Запрос");
ТекстЗапроса =
"//{{ЗАПРОС(Сформировать)
|Период с НачДата по КонДата;
|ВидТоплива = Регистр.ПокупателиКолво.ВидыТоплива;
|Покуп = Регистр.ПокупателиКопво.Покупатели;
|Док = Регистр.ПокупателиКолво.ТекущийДокумент;
|Ном = Регистр.ПокупателиКолво.НомерСтроки;
|Вес = Регистр.ПокупателиКолво.Кг;
|Группировка ВидТоплива; // по измерению Регистра
|Группировка Док; //по документам, двигавшим Регистр
|Группировка Ном; // по номерам строк документов
|Функция ВсегоКолво = КонОст(Вес);
|Функция ПриходКолво = Приход(Вес);
|Условие(Покуп = Покупат);
|"
;

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

В программном модуле конфигурации (т.е. вне текста запроса) существует доступ (там, где это имеет смысл) к значениям всех объявленных в тексте запроса внутренних переменных, даже тех, которые не участвуют ни в группировках, ни в функциях. Другими словами, если объявленная в тексте запроса внутренняя переменная не задействована в запросе ни в группировке, ни в функции, ни в условии, данная внутренняя переменная всё же присутствует в запросе.

Операторы языка запросов

Установить интервал дат формирования запроса позволяет оператор Период С ... По (англоязычный синоним — Period From ... Till). Если в описании запроса оператор Период С ... По опущен, то интервал дат формирования запроса устанавливается в точку актуальности итогов (ТА) (или на рабочую дату, если не установлена компонента «Оперативный учет»), запрос формируется только на этот момент времени.

Использование данного оператора актуально только в том случае, если запрос строится для выборки данных по регистрам, журналам расчётов и/или документам. Здесь указывается, в каком интервале выбирать движения регистров и/или подборку документов. При выполнении запроса только по справочникам эта секция не играет никакой роли.

Синтаксис оператора:

[[Период] С <Дата>|<ВнешПеременная> [По <Дата>|<ВнешПеременная>];]

где

  • <Дата> — константа типа "Дата", "Документ" или позиция документа;
  • <ВнешПеременная> — внешняя переменная типа "Дата", "Документ" или позиция документа. Если указан документ, то за момент времени принимается дата и время документа;
  • По — добавочное ключевое слово для связки первой части команды со второй, необязательной частью.

Параметрами оператора Период С являются значения момента времени ("Дата", "Документ" или позиция документа) начала и конца временного интервала. Следует особо обратить внимание, что если интервал задаётся с точностью до даты, то интервал времени считается от начала даты нижней границы интервала до конца даты верхней границы интервала. Если вторая часть оператора после ключевого слова По пропущена или значение второго параметра команды равно нулю, то интервал времени применяется от начального момента времени до ТА (или по рабочую дату, если не установлена компонента «Оперативный учет»). Это особенно важно при формировании запросов по регистрам, так как запрос по регистрам может строиться от любой даты в прошлом до ТА. Поэтому, если вы укажете в запросе верхнюю границу интервала большей или равной дате ТА, то программа, скорее всего, сообщит «Не могу рассчитать регистры за ТА» (поскольку время ТА лежит где то в пределах даты, а запрос пытается учесть всю дату в целом). Поэтому при формировании текста запроса следует вставлять дополнительную проверку типа той, что приведена в следующем примере:

Запрос = СоздатьОбъект("Запрос");
ТекстЗапроса =
 . . .
|Счет = Регистр.Cash.Счет;
|Статья = Регистр.Cash.Статья;
|СуммаЭквивалента2 = Регистр.Cash.СуммаЭквивалента2;
|СуммаЭквивалента1 = Регистр.Cash.СуммаЭквивалента1;
 . . .

Если ДатаКонца >= ПолучитьДатуТА() Тогда
   ТекстЗапроса = ТекстЗапроса + "Период с ДатаНачала;";
Иначе
   ТекстЗапроса = ТекстЗапроса + "Период с ДатаНачала по ДатаКонца;";
КонецЕсли;
Если Запрос.Выполнить(ТекстЗапроса) = 0 Тогда
   Возврат;
КонецЕсли;

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

Применение конструкции С ... По ... приводит к тому, что выборка записей из журнала расчётов проводится по времени действия записей журнала расчётов, определяемых реквизитами журнала расчётов ДатаНачала и ДатаОкончания, а не временем их ввода в журнал.

Примечание: Работа запроса с журналами расчётов, с использованием конструкции Период С ... По ..., аналогична выборке записей в журнале расчётов, организуемой при помощи метода журнала расчётов ВыбратьПериод(). С другой стороны, запрос, использующий конструкцию С ... По ..., аналогичен выборке, организуемой при помощи метода журнала расчётов ВыбратьЗаписи().

Пример 1:

Процедура РасчЛистки()
   Перем Запрос, Флаг;
   Перем ДатаНач, ДатаКон;
   ЖР = СоздатьОбъект("ЖурналРасчетов.Зарплата");
   ДатаНач = ЖР.НачалоТекущегоПериода();
   ДатаКон = ЖР.КонецТекущегоПериода();
   
   Запрос = СоздатьОбъект("Запрос");
   Флаг = Запрос.Выполнить(
   "//{{ЗАПРОС(РасчЛистки)
   |Период С ДатаНач По ДатаКон; // выборка по расчетным периодам!
   |Рез = ЖурналРасчетов.Зарплата.Результат;
   |Расч = ЖурналРасчетов.Зарплата.ВидРасч;
   |Дни = ЖурналРасчетов.Зарплата.Дни;
   |Сотр = ЖурналРасчетов.Зарплата.Объект;
   |Группировка Сотр без групп;
   |Группировка Расч;
   |функция Сум = Сумма(Рез);
   |функция Дней = Сумма(Дни);
   |Условие(Рез о 0);
   |"
   );
    . . .
КонецПроцедуры;

Пример 2:

Запрос = СоздатьОбъект("Запрос");

ТекстЗапроса =
"//{{ЗАПРОС(Сформировать)
|С ДатаНач По ДатаКон;
|Рез = ЖурналРасчетов.Зарплата.Результат;
|Сотр = ЖурналРасчетов.Зарплата.Объект;
|ПЖ = ЖурналРасчетов.Зарплата.ПериодРегистрации;
|Группировка Сотр без групп;
|Группировка ПЖ;
|Функция Сум = Сумма(Рез);
|"
;
Флаг = Запрос.Выполнить(ТекстЗапроса);
 . . .

Назначить режим обработки документов в запросе позволяет оператор ОбрабатыватьДокументы (англоязычный синоним — ProcessDocuments). В операторе указывается, какими документами должен оперировать запрос: непроведёнными (NonTransacted), проведёнными (Transacted) или теми и другими (All). По умолчанию в запросе обрабатываются только проведённые документы.

Синтаксис оператора:

ОбрабатыватьДокументы [Непроведенные|Проведенные|Все];

где Непроведенные, Проведенные, Все — указание, какие документы следует обрабатывать.

Пример:

Запрос = СоздатьОбъект("Запрос");
ТекстЗапроса =
"//{{ЗАПРОС(ОбработкаДок)
|Период с '01.10.96' по '05.10.96';
|ОбрабатыватьДокументы Все;
|Тов = Справочник.Товары.ТекущийЭлемент, Документ.РасхНакл.Товар;
|Группировка Тов упорядочить по Тов.Наименование;
|Группировка Документ;
|Группировка СтрокаДокумента;
|"
;
Если Запрос.Выполнить(ТекстЗапроса) = 0 Тогда
   Возврат;
КонецЕсли;

Назначить режим обработки бухгалтерских операций в запросе позволяет оператор ОбрабатыватьОперации (англоязычный синоним — ProcessOperations). В операторе указывается, какими операциями должен оперировать запрос: с включенными проводками (On), с выключенными проводками (Off) или теми и другими (All). По умолчанию в запросе обрабатываются только операции с включенными проводками.

Синтаксис оператора:

ОбрабатыватьОперации [Включенные|Выключенные|Все];

где Включенные, Выключенные, Все — указание, какие операции следует обрабатывать.

Пример:

Запрос = СоздатьОбъект("Запрос");
ТекстЗапроса =
"//{{ЗАПРОС(ОбработкаОпер)
|Период с '01.10.96' по '05.10.96';
|ОбрабатыватьОперации Все;
|Опер = Операция.ТекущийДокумент;
|Группировка Опер;
|"
;
Если Запрос.Выполнить(ТекстЗапроса) = 0 Тогда
   Возврат;
КонецЕсли;

Назначить режим обработки помеченных на удаление объектов в запросе позволяет оператор Обрабатывать (англоязычный синоним — Process). В операторе указывается, какими объектами должен оперировать запрос: не помеченными на удаление (NonMarkedOnRemoving), помеченными на удаление (MarkedOnRemoving) или теми и другими (All). По умолчанию в запросе обрабатываются все объекты.

Синтаксис оператора:

Обрабатывать [ПомеченныеНаУдаление|НеПомеченныеНаУдаление|Все];

где ПомеченныеНаУдаление, НеПомеченныеНаУдаление, Все — указание, какие объекты следует обрабатывать.

Пример:

Запрос = СоздатьОбъект("Запрос");
ТекстЗапроса =
"//{{ЗАПРОС(Обработка)
|Период с '01.10.96' по '05.10.96';
|Обрабатывать НеПомеченныеНаУдаление;
|Товар = Справочник.Товар.ТекущийЭлемент;
|Группировка Товар упорядочить по Товар.Наименование;
|"
;
Если Запрос.Выполнить(ТекстЗапроса) = 0 Тогда
   Возврат;
КонецЕсли;

Вычислить указанный тип функции и присваивает её значение внутренней переменной позволяет оператор Функция (англоязычный синоним — Function).

Синтаксис оператора:

Функция <ИмяФункции> = <ТипФункции> (<Параметр>|<УточненныйПараметр>) [Когда (<Условие>)];

где

  • <ИмяФункции> — имя, которое присваивается функции. По этому имени можно в дальнейшем обращаться к значению вычисленной функции из вызывающего программного модуля как к атрибуту запроса. Данную внутреннюю переменную заранее объявлять не нужно. Она фактически неявно объявляется в операторе Функция;
  • <ТипФункции> — ключевое слово одной из встроенных функций языка (см. список типов ниже);
  • <Параметр> — имя объявленной ранее внутренней переменной, значение которой используется как параметр встроенной функции. В функциях Сумма, Среднее, Максимум, Минимум в качестве данного параметра возможно использование арифметического выражения в терминах встроенного языка «1С:Предприятие»;
  • <УточненныйПараметр> — конкретизация объявленной ранее внутренней переменной, значение которой используется как аргумент встроенной функции;
  • Когда (англ. When) — необязательное добавочное ключевое слово, использование которого в команде означает, что вычисление функции следует производить только при условии, когда заданное логическое выражение <Условие> истинно;
  • <Условие> — логическое выражение встроенного языка «1С:Предприятие». В логическом выражении могут участвовать как внутренние, так и внешние переменные запроса. Используется только после ключевого слова Когда.

Типы применяемых функций предопределены и могут быть следующими:

  • Сумма (Sum) — вычисляет сумму выбранных по запросу значений параметра*;
  • Среднее (Avg) — вычисляет среднее из выбранных по запросу значений параметра;
  • Минимум (Min) — вычисляет минимум из выбранных по запросу значений параметра;
  • Максимум (Мах) — вычисляет максимум из выбранных по запросу значений параметра;
  • Счётчик (Count) — подсчитывает количество записей, вошедших в выборку;
  • НачОст (BegRest) — вычисляет начальный остаток для выбранных по запросу значений параметра**;
  • КонОст (EndRest) — вычисляет конечный остаток для выбранных по запросу значений параметра**;
  • Приход (Debit) — вычисляет приход для выбранных но запросу значений параметра**;
  • Расход (Credit) — вычисляет расход для выбранных по запросу значений параметра**;
  • СНД (IDB) — вычисляет сальдо начальное дебетовое для выбранных по запросу значений параметра***;
  • СКД (FDB) — вычисляет сальдо конечное дебетовое для выбранных по запросу
    значений параметра***;
  • СНК (ICD) — вычисляет сальдо начальное кредитовое для выбранных по запросу значений параметра***;
  • СКК (FCD) — вычисляет сальдо конечное кредитовое для выбранных по запросу значений параметра***;
  • ДО (TD) — вычисляет дебетовые обороты для выбранных по запросу значений параметра***;
  • КО (TC) — вычисляет кредитовые обороты для выбран
    ных по запросу значений параметра***;
  • КорДО (CorTD) — вычисляет дебетовые обороты между корреспондирующим счетам или субконто для выбранных по запросу значений параметра****;
  • КорКО (CorTC) — вычисляет кредитовые обороты между корреспондирующим счетам или субконто для выбранных по запросу значений параметра****;

Примечания:

* Для ресурсов оборотных регистров допускается вызывать только тип функции "Сумма".

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

*** Функции "СНД", "СНК", "СКД", "СКК", "ДО", "КО" можно использовать только с реквизитами проводки: Сумма, Количество или ВалСумма.

**** Функции "КорДО" и "КорКО" можно использовать только с реквизитами проводки: Сумма, Количество или ВалСумма. Функции накапливают значения только тогда, когда в запросе есть обращение к реквизитам проводок Счет, КорСчет, Субконто или КорСубконто.

Примечание 5: В программном модуле, где используется запрос, <ИмяФункции> будет являться атрибутом запроса. При помощи данного атрибута можно обращаться к значению вычисленной в запросе функции.

Примечание 6: В функциях "Сумма", "Среднее", "Максимум", "Минимум" в качестве аргумента возможно использование арифметического выражения в терминах встроенного языка.

Пример:

 . . .
|КолВо = Документ.ВидДокумента.Количество;
|Цена = Документ.ВидДокумента.Цена;
|Функция Сум = Сумма(КолВо * Цена);
|Функция Макс = Максимум(Окр(КолВо) * Окр(Цена));
|Функция Средн = Среднее(ФункцияОпределеннаяВМодуле(КолВо, Цена));
 . . .

Другой пример:

Запрос = СоздатьОбъект("Запрос");
ТекстЗапроса =
"//ЗАПРОС(Функции)
|Период с ДатаНач по ДатаКон;
|Оклад = Справочник.Сотрудники.Оклад;
|Подр = Справочник.Сотрудники.Подразделение;
|Ктг = Справочник.Сотрудники.Категория;
|Группировка Подр без групп;
|Группировка Ктг без групп;
|Функция Всего = Сумма(Оклад);
|Условие((Ктг.Выбран() = 1) И (Подр.Выбран() = 1));
|"
;
Если Запрос.Выполнить(ТекстЗапроса) = 0 Тогда
   Возврат;
КонецЕсли;
 . . .
Итог = Запрос.Всего;
 . . .

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

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

При создании в тексте запроса внутренней переменной, которую вы предполагаете использовать в качестве параметра оператора Функция, надо учитывать, что тип этой внутренней переменной должен быть "Число", так как функции в языке запросов обрабатывают только числовые значения.

В тексте запроса, при описании оператора Функция можно использовать необязательное ключевое слово Когда, использование которого в операторе означает, что вычисление функции следует производить только при условии, что значение логического выражения, заданного в параметре ключевого слова является "Истина". Синтаксис применяемого логического выражения полностью аналогичен синтаксису разрешённому к применению в операторах Условие.

Следует понимать, что не все функции внутри конкретной группировки запроса могут иметь чётко интерпретируемый смысл. Например, для группировки по документу движения регистра следующие функции

|Функция ПрихКол = Приход(Количество);
|Функция РасхКол = Расход(Количество);

имеют четкий смысл — приращения, сделанные документом при движении регистра. С другой стороны, в той же группировке следующие функции

|Функция НачКол = НачОст(Количество);
|Функция КонКол = КонОст(Количество);

явно не имеют смысла (в запросах по регистрам, обычно задают период запроса при помощи оператора Период C. Функция "НачКол" в данном примере должна по смыслу показывать остаток ресурса Количество на начальную дату запроса. Внутри группировки по документу вопрос: «Какой начальный остаток ресурса на дату 10.01.97?» по документу, проведённому, например, 13.01.97, не имеет смысла). Поэтому в таких ситуациях функция будет иметь нулевое значение.

Пример:

Запрос = СоздатьОбъект("Запрос");
ТекстЗапроса =
"//ЗАПРОС(Функции)
|Период с ДатаОтчета;
|Товар = Регистр.КвотыТоваров.Товар;
|Отдел = Регистр.КвотыТоваров.Отдел;
|Сотрудник = Регистр.КвотыТоваров.Сотрудник;
|Партнер = Регистр.КвотыТоваров.Партнер;
|Док = Регистр.КвотыТоваров.ТекущийДокумент;
|Количество = Регистр.КвотыТоваров.КвотаТовара;
|Группировка Товар;
|Группировка Отдел;
|Группировка Сотрудник;
|Группировка Партнер;
|Группировка Док;
|Функция НачКол = НачОст(Количество);
|Функция ПрихКол = Приход(Количество);
|Функция РасхКол = Расход(Количество);
|Функция КонКол = КонОст(Количество);
|// Следующие Функции вычисляем только при определенных
|// условиях, чтобы получить отфильтрованные итоги
|Функция ПрихКолТов = Приход(Количество) Когда (Док.ФлагТовара = 1);
|Функция РасхКолТов = Расход(Количество) Когда (Док.ФлагТовара = 1);
|Функция ПрихКолОтд = Приход(Количество) Когда (Док.ФлагОтдела = 1);
|Функция РасхКолОтд = Расход(Количество) Когда (Док.ФлагОтдела = 1);
|Функция ПрихКолСотр = Приход(Количество) Когда (Док.ФлагСотрудника = 1);
|Функция РасхКолСотр = Расход(Количество) Когда (Док.ФлагСотрудника = 1);
|"
;

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

Задать способ группировки информации и порядок её упорядочивания в запросе позволяет оператор Группировка (англоязычный синоним — Group). От способа группировки информации и порядка её упорядочивания в запросе зависит последующий порядок её выборки.

Синтаксис оператора:

Группировка <ИмяГруппировки>|<ПредопредГруппировка> [Упорядочить по <Порядок>[, <Порядок&#gt;]*]
            [Без Упорядочивания][Без Групп][Все [ВошедшиеВЗапрос]];

где

  • <ИмяГруппировки> — имя объявленной ранее внутренней переменной, по значению которой устанавливается порядок выборки. По этому имени можно в дальнейшем обращаться к значению группировки из вызывающего программного модуля как к атрибуту запроса;
  • <ПредопредГруппировка> — ключевое слово одной из встроенных предопределенных группировок языка запросов (см. список ниже). По этому имени можно будет обращаться к значению группировки из вызывающего программного модуля;
  • Упорядочить по (англ. Order By) — необязательное добавочное ключевое слово. Параметры, следующие за данным ключевым словом, определяют упорядочивание строк в группировке. По умолчанию документы упорядочиваются по дате и времени документов, справочники — по коду или наименованию, в зависимости от основного представления, заданного при описании справочника в Конфигураторе;
  • <Порядок> — используется только после ключевого слова Упорядочить по. Конкретизация внутренней переменной <ИмяГруппировки>, значение которой является параметром упорядочивания строк в группировке. Кроме того, в данном параметре можно использовать имя функции, объявленной в этом же запросе в операторе Функция;
  • Без Упорядочивания (англ. Without Order) — необязательное добавочное ключевое слово, которое преследует цель уменьшения времени формирования запроса, при условии, что ни упорядочивание, ни значения упорядочивания при использовании данного запроса не нужны;
  • Без Групп (англ. Without Groups) — необязательное добавочное ключевое слово, использование которого назначает вывод в запрос только простых элементов справочников (исключая группы). Используется только для группировок, построенных на основе внутренней переменной типа "Справочник";
  • Все (англ. All) — необязательное добавочное ключевое слово, действие которого зависит от типа внутренней переменной, на основе которой построена группировка. Используется только для группировок, построенных на основе внутренней переменной типа "Справочник", или для предопределённых группировок, задающих временной интервал (Год, Месяц, Квартал, Неделя, День). Для предопределённых временных группировок подразумевается, что в запрос будут включены любые значения данных (в том числе нулевые) в каждый заданный момент времени с даты начала запроса по дату конца запроса (интервал задаётся оператором Период С...). Для группировок по справочникам подразумевается, что в запрос будут включены любые значения данных (в том числе нулевые) для каждого допустимого элемента справочника;
  • ВошедшиеВЗапрос (англ. IncludedInQuery) — необязательное добавочное ключевое слово действие которого уточняет предыдущее ключевое слово Все. Использование данного слова подразумевает, что в каждую строку запроса будут включены значения данных (в том числе нулевые), для которых есть ненулевое значение хотя бы в одной строке запроса.

Предопределённые группировки могут быть следующими:

  • Документ (Document) — позволяет детализацию до каждого документа;
  • СтрокаДокумента (DocumentLine) — позволяет детализацию до каждой строки табличной части каждого документа;
  • День (Day), Неделя (Week), Месяц (Month), Квартал (Quarter), Год (Year) — группировки по дате, дают возможность накапливать значения по документам за конкретный период (на каждый день, неделю, месяц и т.д.). В запросе может присутствовать несколько группировок такого типа.

Замечание: В программном модуле, где используется запрос, имя <ИмяГруппировки> (или <ПредопредГруппировка>) будет являться атрибутом запроса. Кроме того, это имя используется в качестве параметра метода запросов Группировка().

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

Несколько операторов Группировка, следующих друг за другом в описании запроса, создают вложенные группировки запроса. Первая группировка — самая старшая, в неё будет вложена следующая группировка, далее будет вложена следующая и т.д. По смыслу, вложенная группировка осуществляет более детальный просмотр объекта внешней группировки. Например, если во внешней группировке мы просматриваем регистр, то во вложенной группировке можно просмотреть документы движений этого регистра, а далее можно сформировать группировку по номерам строк этих документов.

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

По умолчанию, документы упорядочиваются в группировке по дате и времени документов, элементы справочников — в зависимости от основного представления, заданного при описании справочника в Конфигураторе (код или наименование). Однако критерий упорядочивания в группировке можно установить при помощи необязательного ключевого слова Упорядочить по. Параметры, следующие за данным ключевым словом, определяют упорядочивание строк в группировке.

С параметром упорядочивания связан специальный метод для доступа к значениям объекта "Запрос". Речь идет об использовании метода ЗначениеУпорядочивания(). В программном модуле, после того как запрос уже сформирован, мы можем при помощи этого метода получить значение поля упорядочивания из временного набора данных, не обращаясь к базе данных. Например, если у нас в запросе была группировка "Товар", а нам для формирования некоторого отчёта нужны значения наименований товаров, то эти наименования товаров можно получить двумя способами:

Наим = Запрос.Товар.Наименование;



Наим = Запрос.ЗначениеУпорядочивания("Товар", 1);

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

Пример:

Процедура Группировки()
   Перем Запрос, ТекстЗапроса;
   Перем ДатаНач, ДатаКон;
   ЖР = СоздатьОбъект("ЖурналРасчетов.Зарплата");
   ДатаНач = ЖР.НачалоТекущегоПериода();
   ДатаКон = ЖР.КонецТекущегоПериода();
   
   Запрос = СоздатьОбъект("Запрос");
   ТекстЗапроса =
   "//{{ЗАПРОС(Группировки)
   |Период с ДатаНач по ДатаКон;
   |Рез = ЖурналРасчетов.Зарплата.Результат;
   |Расч = ЖурналРасчетов.Зарплата.ВидРасч;
   |Дни = ЖурналРасчетов.Зарплата.Дни;
   |Сотр = ЖурналРасчетов.Зарплата.Объект;
   |Группировка Сотр без групп;
   |Группировка Расч;
   |Функция Сум = Сумма(Рез);
   |Функция Дней = Сумма(Дни);
   |Условие(Рез о 0);
   |"
   ;
   
   Если Запрос.Выполнить(ТекстЗапроса) = 0 Тогда
      Возврат;
   КонецЕсли;
   
   Таб = СоздатьОбъект("Таблица");
   Пока Запрос.Группировка("Сотр") = 1 Цикл
      
      Таб.ВывестиСекцию("Сотр");
      Пока Запрос.Группировка("Расч") = 1 Цикл
         
         Таб.ВывестиСекцию("Расч");
      КонецЦикла;
   КонецЦикла;
   Таб.Опции(0, 0, 0, 0);
   Таб.ТолькоПросмотр(1);
   Таб.Показать("Результат", );
КонецПроцедуры

Увеличить скорости выполнения запроса, если итоговые записи при использовании запроса не нужны, позволяет оператор Без итогов (англоязычный синоним — Without Totals). Данный оператор языка запросов, даёт возможность не накапливать итоги по группировкам. Использовать данный оператор в тексте запроса имеет смысл, когда запрос строится не для формирования сложного отчёта, а например, для простой выборки значений из информационной базы для последующей их обработки.

В случае применения данного оператора в тексте запроса, при обходе результатов запроса применяется только один цикл обхода, используя метод объекта "Запрос" Группировка() без параметра.

Пример:

Запрос = СоздатьОбъект("Запрос");
Текст3апроса = "
 . . .
|Группировка Товар;
|Группировка Склад;
|Без Итогов;
|"
;
Если Запрос.Выполнить(ТекстЗапроса) = 1 Тогда
   Возврат;
КонецЕсли;

Пока Запрос.Группировка() = 1 Цикл
    . . .
КонецЦикла;

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

Задать условие включения информации в запрос позволяет оператор Условие (англоязычный синоним — Condition). Если указанное в качестве параметра логическое выражение истинно, то информация включается в запрос, иначе нет.

Синтаксис оператора:

Условие(<ЛогическоеВыражение>);

где <ЛогическоеВыражение> — логическое выражение встроенного языка «1С:Предприятие». В логическом выражении могут участвовать как внутренние, так и внешние переменные запроса, то есть переменные программного модуля, доступные в процедуре, использующей запрос.

Пример:

ТекстЗапроса =
"//{{ЗАПРОС(Одинарный)
|Период с ДатаНачала по ДатаКонец;
|Оклад = Справочник.Сотрудники.Оклад;
|Ктг = Справочник.Сотрудники.Категория;
|Группировка Ктг без групп;
|Функция Всего = Сумма(Оклад);
|Условие(Ктг.Выбран() = 1);   // только для тех сотрудников
| // у кого заполнен реквизит Категория
|"
;

Далее в нижеприведённом примере показан отрывок текста процедуры, в которой формируется некоторый отчёт, причём переменные ВыбТовар, ВыбОтдел, ВыбСотрудник являются реквизитами диалога отчёта, значит, они доступны в программном модуле, поэтому могут быть использованы в логическом выражении оператора Условие(). В данном примере операторы Условие() использованы для фильтрации в запросе только выбранных значений параметров отчёта:

Запрос = СоздатьОбъект("Запрос");
ТекстЗапроса =
"//{{ЗАПРОС(Квоты)
|Товар = Регистр.КвотыТоваров.Товар;
|Отдел = Регистр.КвотыТоваров.Отдел;
|Сотрудник = Регистр.КвотыТоваров.Сотрудник;
|Партнер = Регистр.КвотыТоваров.Партнер;
|Количество = Регистр.КвотыТоваров.КвотаТовара;
|Группировка Товар;
|Группировка Отдел;
|Группировка Сотрудник;
|Группировка Партнер;
|Функция Кол_во = КонОст(Количество);
|Условие(Товар.ПринадлежитГруппе(ВыбТовар) = 1);
|Условие(Отдел = ВыбОтдел);
|Условие(Сотрудник = ВыбСотрудник.Сотрудник);
|"
;

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

В параметре оператора Условие(), в принципе, можно записывать логические выражения любой сложности (по правилам встроенного языка «1С:Предприятие»), используя любые логические операторы (>, <, =, >=, <>, И, ИЛИ, НЕ и др.), при этом в качестве операндов могут участвовать как внутренние, так и внешние переменные запроса (если существуют внутренняя и внешняя переменные с одинаковым именем, то использоваться по данному имени будет внутренняя переменная).

Пример:

Условие(Цена > 23.5);
Условие((Товар.ПринадлежитГруппе(ВыбТовар) = 1) И (Товар.Розн_Цена = 100));

Использование двух операторов

Условие(Товар.Наименование <> "Стол");
Условие(Товар.Наименование <> "Шкаф");

аналогично одному оператору

Условие((Товар.Наименование <> "Стол") И (Товар.Наименование <> "Шкаф"));

Кроме обычных логических операторов в операторе Условие() языка запросов можно использовать дополнительный оператор — логический оператор принадлежности В (англоязычный синоним — In). Тогда, например, оператор языка запросов Условие (А в Б); будет говорить о том, что условие истинно, когда значение А является подмножеством значения Б. Причём, следует особо отметить, что если значение Б будет пустое (объект не выбран), то условие будет является истинным, в отличии от оператора = (равно).

Если на принадлежность проверяется значение типа "элемент справочника", то проверка выполняется с учётом его возможного вхождения в группу справочника. Аналогично, проверка на принадлежность субсчёта осуществляется с учётом его возможного вхождения в группу счетов.

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

Оператор принадлежности существенно облегчает написание текстов запроса, делает их более понятными. Рассмотрим пример запроса без использования логического оператора принадлежности:

Текст3апроса = "
 . . .
|Товар = Документ.ВидДокумента.Товар;";
 . . .
|"
;

Если ВыбТовар.Выбран() = 1 Тогда
   Если ВыбТовар.ЭтоГруппа() = 1 Тогда
      ТекстЗапроса = ТекстЗапроса + "Условие(Товар.ПринадлежитГруппе(ВыбТовар) = 1);";
   Иначе
      ТекстЗапроса = ТекстЗапроса + "Условие(Товар = ВыбТовар);";
   КонецЕсли
КонецЕсли;

А теперь тот же пример, но с использованием логического оператора принадлежности:

Текст3апроса = "
 . . .
|Товар = Документ.ВидДокумента.Товар;";
 . . .
|Условие(Товар В ВыбТовар);
 . . .
|"
;

Примеры использования запросов

Печать каталога товаров

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

Процедура ПечатьСправочника()
   
   Перем Запрос, ТекстЗапроса, Таб;
   
   Запрос = СоздатьОбъект("Запрос");
   Текст3апроса = "//{{ЗАПРОС(Печать)
   |Товар = Справочник.Товары.ТекущийЭлемент;
   |Группировка Товар Упорядочить по Товар.МинЗапас;
   |"
   ;
   
   Если Запрос.Выполнить(ТекстЗапроса) = 0 Тогда
      Возврат;
   КонецЕсли;
   
   Таб = СоздатьОбъект("Таблица");
   Таб.ВывестиСекцию("Отчет");
   Пока Запрос.Группировка("Товар") = 1 Цикл
      
      Если Запрос.Товар.ЭтоГруппа() = 1 Тогда
         Таб.ВывестиСекцию("Группа");
      Иначе
         Таб.ВывестиСекцию("Товар");
      КонецЕсли;
   КонецЦикла;
   
   Таб.Опции(0, 0, 4, 0);
   Таб.ТолькоПросмотр(1);
   Таб.Показать("Список товаров по каталогу", "");
КонецПроцедуры

Отчёт по неходовым товарам

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

Процедура Сформировать()
   Перем Запрос, ТекстЗапроса, Таб;
   Рег = СоздатьОбъект("Регистр.ОстаткиТовара");
   Запрос = СоздатьОбъект("Запрос");
   ТекстЗапроса = "//{{ЗАПРОС(Сформировать)
   |Период С ДатаНачала По ДатаКонца;
   |ТОВАР = Документ.РасходнаяБН.Товар, 
   |   Документ.РасходнаяКредит.Товар, Документ.РасходнаяНал.Товар,
   |   Документ.РасходнаяРеализ.Товар, Документ.Счет.Товар;
   |Группировка ТОВАР упорядочить по ТОВАР.Наименование без групп;
   |"
   ;
   Если ДатаКонца >= ПолучитьДатуТА() Тогда
      ТекстЗапроса = ТекстЗапроса + "Период С ДатаНачала;";
   Иначе
      ТекстЗапроса = ТекстЗапроса + "Период С ДатаНачала По ДатаКонца;";
      Peг.ВременныйРасчет();
      РассчитатьРегистрыНа(ДатаКонца);
   КонецЕсли;
   
   Если Запрос.Выполнить(ТекстЗапроса) = 0 Тогда
      Возврат;
   КонецЕсли;
   Тов = СоздатьОбъект("Справочник.Товары");
   
   Тов.ВключатьПодчиненные(1);
   
   Тов.ПорядокНаименований();
   ИтогоОстаток = 0;
   ИтогоСумма = 0;
   Таб = СоздатьОбъект("Таблица");
   Таб.ВывестиСекцию("Отчет");
   
   Тов.ВыбратьЭлементы();
   Пока Тов.ПолучитьЭлемент() > 0 Цикл
      Флаг = 0;
      Товар = Тов.ТекущийЭлемент();
      Если Товар.ЭтоГруппа() = 1 Тогда
         Продолжить;
      КонецЕсли;
      
      Если Запрос.Получить(Товар) = 1 Тогда
         Продолжить;
      КонецЕсли;
      
      Рег.СводныеОстатки(Товар, );
      ТекОстаток = Рег.ОстатокТовара;
      ТекСумма = Рег.БазоваяСтоимость;
      Если ТекОстаток = 0 Тогда
         Продолжить;
      КонецЕсли;
      Таб.ВывестиСекцию("Товар");
      ИтогоОстаток = ИтогоОстаток + ТекОстаток;
      ИтогоСумма = ИтогоСумма + ТекСумма;
   КонецЦикла;
   Таб.ВывестиСекцию("Итоги");
   Таб.ТолькоПросмотр(1);
   Таб.Опции(0, 0, 3, 0);
   Таб.Показать("Отчет о неходовых товарах", "");
КонецПроцедуры



ДатаКонца = РабочаяДата();
ДатаНачала = ДатаКонца — Константа.ПериодАнализа;

Отчёт по регистру с точностью до строки документа

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

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

Процедура Сформировать()
   Перем Запрос, ТекстЗапроса, Таб;
   
   Запрос = СоздатьОбъект("Запрос");
   ТекстЗапроса = "//{{ЗАПРОС(Сформировать)
   |Период с НачДата по КонДата;
   |ВидТоплива = Регистр.ПокупателиКолво.ВидыТоплива;
   |Вес = Регистр.ПокупателиКолво.Кг;
   |Покуп = Регистр.ПокупателиКолво.Покупатели;
   |Док = Регистр.ПокупателиКолво.ТекущийДокумент;
   |Ном = Регистр.ПокупателиКолво.НомерСтроки;
   |Группировка ВидТоплива;      // по измерению Регистра
   |Группировка Док;             // по документам, двигавшим Регистр
   |Группировка Ном;             // по номерам строк документов
   |Функция ВсегоКолво = КонОст(Вес);
   |Функция ПриходКолво = Приход(Вес);
   |Условие(Покуп = ВыбПокупатель);
   |"
   ;
   
   Если Запрос.Выполнить(ТекстЗапроса) = 0 Тогда
      Возврат;
   КонецЕсли;
   
   Таб = СоздатьОбъект("Таблица");
   Таб.ИсходнаяТаблица("Таблица1");
   Таб.ВывестиСекцию("Шапка");
   Пока Запрос.Группировка(1) = 1 Цикл
      
      Таб.ВывестиСекцию("ВидТоплива");
      
      Пока Запрос.Группировка(2) = 1 Цикл
         Док1 = Запрос.Док;
         
         Если НЕ(Док1.Вид() = "Продажа") Тогда
            Продолжить;
         КонецЕсли;
         
         Пока Запрос.Группировка(3) = 1 Цикл
            
            Док1.ПолучитьСтрокуПоНомеру(Запрос.Ном);
            Таб.ВывестиСекцию("Строка");
         КонецЦикла;
      КонецЦикла;
   КонецЦикла;
   
   Таб.Опции(0, 0, 0, 0);
   Таб.ТолькоПросмотр(1);
   Таб.Показать("", "");
КонецПроцедуры

Анализ счёта

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

Процедура АнализСчета()
   Перем Запрос, ТекстЗапроса, Таб;
   
   Запрос = СоздатьОбъект("Запрос");
   ТекстЗапроса = "//{{ЗАПРОС(Сформировать)
   |Период с ДатаС по ДатаПо;
   |Сч = Операция.Счет;
   |КорСч = Операция.КорСчет;
   |Сумма = Операция.Сумма;
   |Группировка Сч упорядочить по Сч.Код;
   |Группировка КорСч упорядочить по КорСч.Код;
   |Функция КорДо = КорДО(Сумма);
   |Функция КорКо = КорКО(Сумма);
   |Условие(Сч = ВыбСч);
   |"
   ;
   
   Если Запрос.Выполнить(ТекстЗапроса) = 0 Тогда
      Возврат;
   КонецЕсли;
   
   Таб = СоздатьОбъект("Таблица");
   Таб.ИсходнаяТаблица("Сформировать");
   
   Таб.ВывестиСекцию("Заголовок");
   Состояние("Заполнение выходной таблицы...");
   Пока Запрос.Группировка("Сч") = 1 Цикл
      
      Таб.ВывестиСекцию("Сч");
      Пока Запрос.Группировка("КорСч") = 1 Цикл
         
         Таб.ВывестиСекцию("КорСч");
      КонецЦикла;
   КонецЦикла;
   
   Таб.ВывестиСекцию("Итого");
   
   Таб.Опции(1, 0, 1, 0);
   Таб.Показать("Сформировать", "");
КонецПроцедуры

Разработка вложенных отчётов

Средства программы «1С:Предприятие» по работе с таблицами позволяют создавать эффектные отчёты, причём на экране монитора отображается не просто мёртвая картинка предварительного просмотра печати, а живой отчёт, который можно редактировать или непосредственно из него вызывать дополнительную поясняющую информацию.

Поскольку каждая ячейка таблицы может содержать значение, записанное в неё, то в программном модуле формы отчёта возможно обрабатывать это значение. Обработка значения ячейки таблицы вызывается системой по клавише Enter или по двойному щелчку мышью на какой-либо ячейке (если режим «только просмотр»). Стандартными действиями системы на обработку такого события являются: для документа — открытие документа, для элемента справочника — открытие формы редактирования элемента справочника. Другими словами, стандартные действия системы зависят от типа данных содержащегося в ячейке значения. Однако, это событие возможно перехватить и обработать нестандартным способом. Для этого предназначена предопределённая процедура встроенного языка ОбработкаЯчейкиТаблицы().

Примером нестандартной обработки значения ячейки таблицы может быть, например, вызов на формирование другого отчёта. Таким образом, мы можем создавать как бы вложенные отчёты, которые вызываются один из другого, выдавая с каждым разом более детальную информацию. Допустим отчёт «Взаиморасчеты» при формировании всегда выводится в кратком виде, когда виден только сводный баланс по контрагенту. Для того, чтобы получить детальный отчёт по данному контрагенту, достаточно встать курсором в готовой форме отчёта на этого контрагента и нажать клавишу Enter. Тогда сработает процедура ОбработкаЯчейкиТаблицы(), в которой можно записать вызов формирования детального отчёта. А если, кроме того, завести флаг режима отображения, то можно вместо этого показывать карточку этого контрагента из справочника.

Рассмотрим построение вложенных отчётов на примере. Допустим, у вас есть отчёт «ПродажиТоваров», в котором отображается перечень товаров, количество и сумма проданных за некоторый период товаров. Программный модуль формирования такого отчёта приведён ниже.

Процедура ПродВсего()
   Перем Запрос, ТекстЗапроса, Таб;
   ДатаКон = ДатаКонца;
   Если ДатаКон >= ПолучитьДатуТА() Тогда
      ДатаКон = Дата(0);
   КонецЕсли;
   
   Запрос = СоздатьОбъект("Запрос");
   ТекстЗапроса = "//{{ЗАПРОС(ПродВсего)
   |Период с ДатаНачала по ДатаКон;
   |ТОВАР = Документ.РасхНакл.Товар;
   |Сумма_Прод = Документ.РасхНакл.СуммаРуб;
   |КОЛВО_Прод = Документ.РасхНакл.Количество;
   |Группировка ТОВАР;
   |Функция Продано = Сумма(КОЛВО_Прод);
   |Функция СуммаПродано = Сумма(Сумма_Прод);
   |"
   ;
   
   Если Запрос.Выполнить(ТекстЗапроса) = 0 Тогда
      Возврат;
   КонецЕсли;
   
   Таб = СоздатьОбъект("Таблица");
   Таб.ИсходнаяТаблица("ТабВсего");
   Таб.ВывестиСекцию("Отчет");
   Пока Запрос.Группировка("Товар") = 1 Цикл
      ПродСумма = Запрос.СуммаПродано;
      Если Запрос.Товар.ЭтоГруппа() = 1 Тогда
         Таб.ВывестиСекцию("Группа");
      Иначе
         Таб.ВывестиСекцию("Товар");
      КонецЕсли;
   КонецЦикла;
   
   Таб.ТолькоПросмотр(1);
   Таб.Опции(0, 0, 4, 0);
   Таб.Показать("Продажа товаров", "");
КонецПроцедуры

В режиме исполнения у нас получится такой отчёт:

Отчёт

Далее, допустим, мы хотим получить более подробный отчёт по конкретному товару, так, чтобы указав на товар в отчёте, и дважды нажав кнопку мыши, мы получали отчёт по продажам именно этого товара с точностью до каждого клиента. Для этого откроем в Конфигураторе редактор таблицы нашего отчёта и в свойствах ячейки (Свойства ячейки -> Текст -> поле «Значение»), отображающей наименование товара, проставим значение ячейки — «Запрос.Товар».

Далее, в программном модуле напишем процедуру формирования дополнительного отчёта:

Процедура ПродТовар(ВТовар)
   Перем Запрос, ТекстЗапроса, Таб;
   ДатаКон = ДатаКонца;
   Если ДатаКон >= ПолучитьДатуТА() Тогда
      ДатаКон = Дата(0);
   КонецЕсли;
   
   Запрос = СоздатьОбъект("Запрос");
   ТекстЗапроса = "//{{ЗАПРОС(ПродТовар)
   |Период с ДатаНачала по ДатаКон;
   |КЛИЕНТ = Документ.РасхНакл.Клиент;
   |ТОВАР = Документ.РасхНакл.Товар;
   |СУММ = Документ.РасхНакл.СуммаВал;
   |КОЛВО = Документ.РасхНакл.Количество;
   |Группировка КЛИЕНТ Упорядочить По КЛИЕНТ.Наименование;
   |Группировка ТОВАР Упорядочить По ТОВАР.Наименование;
   |Функция Продано = Сумма(КОЛВО);
   |Функция ПродСум = Сумма(СУММ);
   |"
   ;
   Если ВТовар.Выбран() = 1 Тогда
      Если ВТовар.ЭтоГруппа() = 1 Тогда
         ТекстЗапроса = ТекстЗапроса + "Условие(Товар.ПринадлежитГруппе(ВТовар) = 1);";
      Иначе
         ТекстЗапроса = ТекстЗапроса + "Условие (Товар = ВТовар);";
         ФОдинТовар = 1;
      КонецЕсли;
   КонецЕсли;
   
   Если Запрос.Выполнить(ТекстЗапроса) = 0 Тогда
      Возврат;
   КонецЕсли;
   
   Таб = СоздатьОбъект("Таблица");
   Таб.ВывестиСекцию("Отчет");
   Пока Запрос.Группировка("Клиент") = 1 Цикл
      Таб.ВывестиСекцию("Клиент");
      Пока Запрос.Группировка("Товар") = 1 Цикл
         Если ФОдинТовар = 0 Тогда
            Таб.ВывестиСекцию("Товар");
         КонецЕсли;
      КонецЦикла;
   КонецЦикла;
   
   Таб.ТолькоПросмотр(1);
   Таб.Опции(0, 4, 0, 0);
   Таб.Показать("Продажа товара", "");
КонецПроцедуры

Теперь нам осталось написать предопределённую процедуру, которая возьмёт на себя обработку события «двойной щелчок мышью на выбранной ячейке таблицы». Главная задача этой процедуры — определить, что выбрана ячейка, где указано значение товара и вызвать на исполнение процедуру формирования дополнительного отчёта, написанную ранее.

Процедура ОбработкаЯчейкиТаблицы(ЗначЯч, ФлагСтандартнойОбработки)   
   Если ТипЗначения(ЗначЯч) = 2 Тогда
      ФлагСтандартнойОбработки = 1;
      Возврат;
   КонецЕсли;
   ПродТовар(ЗначЯч);
КонецПроцедуры

Теперь, в режиме исполнения, если в отчёте «Продажи товаров» мы укажем курсором на товар, например, «Сапоги женские» и дважды щёлкнем на нём мышью, то сформируется дополнительный подробный отчёт «Продажа товара».

Способы оптимизации формирования отчётов

Процесс получения отчётов с использованием запросов можно условно разделить на две фазы: сначала формируется запрос, затем полученные данные выводятся в таблицу. В данном разделе речь пойдёт о второй фазе получения отчёта — выводе данных в таблицу.

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

Вариант 1:

В программном модуле текст вывода данных в таблицу следующий:

Пока Запрос.Группировка("Товар") = 1 Цикл
   Таб.ВывестиСекцию("Товар");
КонецЦикла;

Секция "Товар" в таблице имеет следующий формат:

Секция'Товар'

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

Вариант 2:

В программном модуле текст вывода данных в таблицу следующий:

Пока Запрос.Группировка("Товар") = 1 Цикл
   ПечНаим = Запрос.Товар.Наименование;
   ПечАртикул = Запрос.Товар.Артикул;
   ПечЦена = Запрос.Товар.Цена;
   ПечВалюта = Запрос.Товар.Валюта;
   Таб.ВывестиСекцию("Товар1");
КонецЦикла;

Секция "Товар1" в таблице имеет следующий формат:

Секция'Товар1'

Во этом варианте отображаемые реквизиты товара вычисляются в программном модуле, а в ячейках таблицы размещены простые выражения — ссылки на идентификаторы программного модуля. Доступ к каждому реквизиту товара, как и в первом варианте, происходит по полному пути: Запрос-Товар-Реквизит. Но в данном варианте фаза вывода данных в таблицу работает быстрее первого варианта (выигрыш примерно 20%), так как в программном модуле выражения вычисляются существенно быстрее, чем выражения, помещённые в ячейках таблицы (программный модуль при загрузке компилируется, а выражения в ячейках таблицы интерпретируются каждый раз при выводе секций).

Вариант 3:

В программном модуле текст вывода данных в таблицу следующий:

Пока Запрос.Группировка("Товар") = 1 Цикл
   Тов = Запрос.Товар;
   ПечНаим = Тов.Наименование;
   ПечАртикул = Тов.Артикул;
   ПечЦена = Тов.Цена;
   ПечВалюта = Тов.Валюта;
   Таб.ВывестиСекцию("Товар1");
КонецЦикла;

Секция «Товар1» в таблице имеет следующий формат:

Секция'Товар1'

В этом варианте отображаемые реквизиты товара также вычисляются в программном модуле, а в ячейках таблицы размещены простые выражения — ссылки на идентификаторы программного модуля. Однако доступ к каждому реквизиту товара происходит по сокращённому пути — через промежуточную переменную: Товар—Реквизит. Поэтому в данном варианте фаза вывода данных в таблицу работает быстрее, чем во втором варианте (выигрыш примерно 20%) и существенно быстрее, чем в первом варианте (выигрыш примерно 40%), так как вычисление значений реквизитов объектов через «одну точку» выполняется быстрее, чем через «две (и более) точки».

Отсюда вывод: при реализации больших отчётов, которые рассчитаны на отображение более сотни строк:

  • не следует размещать сложные выражения в ячейках таблицы. Лучше вычислить необходимые значения непосредственно в программном модуле;
  • если необходимо получить несколько реквизитов одного объекта, который сам является составной частью другого объекта, то следует воспользоваться промежуточной переменной, в которую сначала можно записать значение всего объекта «целиком», а затем уже от неё получать требуемые данные.

Другие статьи по схожей тематике

  • Работы с табличными формами
  • Работа со справочниками в 1С
  • Работа с объектами типа "Документ"
  • Работа с типом данных "Счет"
  • Работа с операциями и проводками
  • Работа с бухгалтерскими итогами
  • Работа с регистрами оперативного учёта

Для формирования и выполнения запросов к документам, справочникам, регистрам, журналам расчётов, планам счетов, бухгалтерским операциям и проводкам в системе используется специальный агрегатный тип данных — "Запрос". Возможности работы со справочниками, документами и журналами расчётов предоставляют достаточно мощные средства получения различной информации об этих объектах. Однако, существует также необходимость в получении информации, сгруппированной определённым образом, которую невозможно или очень сложно получить, непосредственно работая с документами, справочниками, регистрами или журналами расчётов. Для получения такой информации и существует механизм запросов.

Рассмотрим основные моменты работы с данным механизмом:

  • Контекст работы с запросами
  • Структура запросов и методика их использования
  • Атрибуты запросов
  • Методы запросов
  • Введение в язык запросов
  • Атрибуты, доступные при описании внутренних переменных
  • Правила объявления внутренних переменных
  • Операторы языка запросов
  • Примеры использования запросов
  • Способы оптимизации формирования отчётов

Контекст работы с запросами

Во всех программных модулях доступ к атрибутам и методам запросов может выполняться только через переменную со ссылкой на объект типа "Запрос", созданный с помощью функции СоздатьОбъект(). Чтобы вызвать атрибут или метод объекта, имя этого атрибута или метода пишется через точку после имени такой переменной.

При создании объекта типа "Запрос" в качестве параметра функции СоздатьОбъект() используется ключевое слово «Запрос» (англоязычный синоним — «Query»).

Запрос = СоздатьОбъект("Запрос");

Структура запросов и методика их использования

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

Запросы можно использовать не только для построения отчётов, но и для реализации других процедур конфигурации, требующих получения из базы данных некой сводной информации. Например, реализация алгоритма списания стоимости товара по методам FIFO или LIFO.

Работа с запросами предполагает следующий порядок:

  • при помощи функции СоздатьОбъект() создаётся объект типа "Запрос" и ссылка на него присваивается какой-либо переменной. Далее обращение к запросу производится посредством этой ссылки;
  • после создания переменной типа "Запрос" следует обращение к методу Выполнить(), которому в качестве параметра передаётся текст запроса, написанный на специальном языке запросов. Метод Выполнить() анализирует текст запроса, выполняет в соответствии с ним выборку данных и формирует временный выходной набор данных (выборку);
  • после этого организуется циклическая обработка сформированного временного набора данных (выборки) с целью получения требуемого отчёта.

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

НашЗапрос = СоздатьОбъект("Запрос");
ТекстЗапроса =
"//{{ЗАПРОС(Сформировать)
|СКЛАД = Регистр.ТоварныйЗапас.Склад;
|ТОВАР = Регистр.ТоварныйЗапас.Товар;
|КОЛИЧЕСТВО = Регистр.ТоварныйЗапас.Количество;
|Группировка ТОВАР Упорядочить По ТОВАР.Код;
|Группировка СКЛАД Упорядочить По СКЛАД.Код;
|Функция КОЛ = КонОст(КОЛИЧЕСТВО);
|"
;

Если НашЗапрос.Выполнить(ТекстЗапроса) = 0 Тогда
   Возврат;
КонецЕсли;

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

Структура временного набора данных

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

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

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

Продолжение примера:

 . . .
Пока НашЗапрос.Группировка("Товар") = 1 Цикл
   
    . . .
КонецЦикла;

 . . .

Поскольку после первого просмотра временного набора данных (как мы это сделали выше) объект НашЗапрос снова спозиционирован на первой записи, то можно запустить просмотр ещё раз.

Допустим, теперь нам надо просмотреть в цикле всю информацию по внешней (Товар) и вложенной группировке запроса (Склад). В теле цикла по внешней группировке (Товар) объект НашЗапрос позиционируется во временном наборе данных на записи, содержащие итоги по каждому конкретному товару, поэтому в теле этого цикла мы можем использовать итоги по товарам.

В теле цикла по вложенной группировке (Склад) объект НашЗапрос позиционируется во временном наборе данных на записи, содержащей строки по каждому конкретному товару на конкретном складе, поэтому в теле этого цикла мы можем использовать данные о количестве товара на складе.

После завершения цикла по вложенной группировке (Склад), объект НашЗапрос снова позиционируется на записи временного набора данных, где содержится общий итог по конкретному товару. Поэтому, общие итоги по конкретному товару можно использовать в двух местах: до и после цикла по вложенной группировке (Склад).

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

Продолжение примера:

 . . .
Пока НашЗапрос.Группировка("Товар") = 1 Цикл
   
    . . .
   Пока НашЗапрос.Группировка("Склад") = 1 Цикл
      
       . . .
   КонецЦикла;
   
    . . .
КонецЦикла;

 . . .

После выхода из процедуры, где была определена переменная, содержащая объект типа "Запрос" (в нашем примере НашЗапрос) или после уничтожения объекта типа "Запрос" (Наш3апрос = 0;), временный набор данных на локальной машине пользователя уничтожается.

Из приведенного выше примера можно сделать несколько важных заключений:

  • при просмотре временного набора данных, вложенность циклов просмотра должна точно повторять порядок группировок запроса (нельзя входить во вложенную группировку, не войдя в предыдущую);
  • допускается просматривать временный набор данных, опуская с некоторого уровня все вложенные (внутренние) группировки;
  • не следует прерывать последовательность просмотра временного набора данных (например, оператором Прервать), если вы собираетесь использовать временный набор дальше или ещё раз, так как в таком случае теряется точка позиционирования во временном наборе и продолжать просмотр невозможно.

Примера обработки запроса:

Пока Запрос.Группировка("Товар") = 1 Цикл
   Если (Запрос.Товар = НужныйТовар) Тогда
      Пока Запрос.Группировка("Отдел") = 1 Цикл
         Если (Запрос.Отдел = НужныйОтдел) Тогда
            Пока Запрос.Группировка("Сотрудник") = 1 Цикл
               Если (Запрос.Сотрудник = НужныйСотрудник) Тогда
                  Пока Запрос.Группировка("Док") = 1 Цикл
                     Док = Запрос.Док;
                     Если Запрос.ПрихКол <> 0 Тогда
                        Таб.ВывестиСекцию("Приход");
                     ИначеЕсли Запрос.РасхКол <> 0 Тогда
                        Приращение = Запрос.РасхКол;
                        Таб.ВывестиСекцию("Расход");
                     КонецЕсли;
                  КонецЦикла;
               КонецЕсли;
            КонецЦикла;
         КонецЕсли;
      КонецЦикла;
   КонецЕсли;
КонецЦикла;

Атрибуты запросов

Атрибутами запроса являются объявленные в описании запроса внутренние переменные (см. далее описание языка запросов), имена группировок и функций запроса. Все атрибуты запросов — только для чтения. Чтобы обратиться к атрибуту запроса, имя этого атрибута пишется через точку после имени ссылки на запрос. Значения атрибутов запроса определяются текущим положением в полученной выборке.

Методы запросов

Выполнить запрос позволяет метод Выполнить() (англоязычный синоним — Execute()). Он анализирует описание, содержащееся в тексте запроса, выполняет выборку данных, формирует временный выходной набор данных (выборку) и вычисляет значения функций запроса. Возвращаемым значением метода является число 1, если запрос выполнен успешно, или 0, если зафиксирована ошибка при выполнении запроса (синтаксическая или времени выполнения).

Синтаксис метода:

Выполнить(<ТекстЗапроса>)

где <ТекстЗапроса> — строковое выражение, содержащее текст запроса на языке запросов.

Пример использования:

Процедура Сформировать()
   
   ЖР = СоздатьОбъект("ЖурналРасчетов.Зарплата");
   _Дата = ЖР.НачалоТекущегоПериода();
   
   Запрос = СоздатьОбъект("Запрос");
   ЗапросКат = СоздатьОбъект("Запрос");
   флаг1 = Запрос.Выполнить(
   "//({ЗАПРОС(Двойной)
   |Период с _Дата по _Дата;
   |Оклад = Справочник.Сотрудники.Оклад;
   |Пдр = Справочник.Сотрудники.МестоРаботы.Владелец;
   |Ктг = Справочник.Сотрудники.Категория;
   |Условие((Ктг.Выбран() = 1) И (Пдр.Выбран() = 1));
   |Группировка Пдр без групп;
   |Группировка Ктг без групп;
   |Функция Всего = Сумма(Оклад);
   |"
   );
   Флаг2 = ЗапросКат.Выполнить(
   "//{{ЗАПРОС(Одинарный)
   |Период с _Дата по _Дата;
   |Оклад = Справочник.Сотрудники.Оклад;
   |Ктг = Справочник.Сотрудники.Категория;
   |Условие(Ктг.Выбран() = 1);
   |Группировка Ктг без групп;
   |Функция Всего = Сумма(Оклад);
   |"
   );
   
   Если ((Флаг1 = 0) ИЛИ (Флаг2 = 0)) Тогда
      Сообщить("Ошибка в запросе!");
      Возврат;
   КонецЕсли;
   
   Таб = СоздатьОбъект("Таблица");
   
   Таб.ВывестиСекцию("Документ<|ДокументВерт<");
   Пока ЗапросКат.Группировка("Ктг") = 1 Цикл
      Таб.ПрисоединитьСекцию("Документ<|Осн2");
   КонецЦикла;
   Таб.ПрисоединитьСекцию("Документ<|ДокументВерт>");
   
   Таб.ВывестиСекцию("КолонТитул|ДокументВерт<");
   Пока ЗапросКат.Группировка("Ктг") = 1 Цикл
      Таб.ПрисоединитьСекцию("КолонТитул|Осн2");
   КонецЦикла;
   Таб.ПрисоединитьСекцию("КолонТитул|ДокументВерт>");
   Продолжать = 1;
   Пока Запрос.Группировка("Пдр") = 1 Цикл
      
      Таб.ВывестиСекцию("Осн1|ДокументВерт<");
      Далее = 1;
      Пока Продолжать = 1 Цикл
         
         СлКат = ЗапросКат.Группировка("Ктг");
         Если Далее = 1 Тогда
            ОК = Запрос.Группировка("Ктг");
         КонецЕсли;
         Если СлКат = 0 Тогда
            Прервать;
         КонецЕсли;
         Если ЗапросКат.Ктг = Запрос.Ктг Тогда
            Таб.ПрисоединитьСекцию("Осн1|Осн2");
            Далее = 1;
         Иначе
            Таб.ПрисоединитьСекцию("Осн1|Пусто");
            Далее = 0;
         КонецЕсли;
      КонецЦикла;
      Таб.ПрисоединитьСекцию("Осн1|ДокументВерт>");
   КонецЦикла;
   
   Таб.ВывестиСекцию("Документ>|ДокументВерт<");
   Пока ЗапросКат.Группировка("Ктг") = 1 Цикл
      Таб.ПрисоединитьСекцию("Документ>|Осн2");
   КонецЦикла;
   Таб.ПрисоединитьСекцию("Документ>|ДокументВерт>");
   
   Таб.Опции(0, 0, 0, 0);
   Таб.ТолькоПросмотр(1);
   Таб.Показать("Результат", );
КонецПроцедуры

Установить режим использования графы отбора в запросе позволяет метод ИспользоватьГрафуОтбора() (англоязычный синоним — UseSelectionColumn()). Если метод не используется — по умолчанию устанавливается автоматический выбор графы отбора. Возвращаемым значением метода является строковое значение — идентификатор использованной реально графы отбора, если метод вызывается после выполнения запроса.

Синтаксис метода:

ИспользоватьГрафуОтбора(<ГрафаОтбора>)

где <ГрафаОтбора> — строковое выражение — идентификатор графы отбора, как он задан в Конфигураторе. Данный параметр устанавливает режим использования определённой графы отбора. Возможными значениями параметра также являются:

  • "*" — автоматический выбор графы отбора;
  • "" (пустая строка) — не использовать графу отбора.

Пример использования:

Запрос = СоздатьОбъект("Запрос");
ТекстЗапроса =
"//{{ЗАПРОС(ОбработкаДок)
|Период с '01.10.96' по '05.10.96';
|ОбрабатыватьДокументы Все;
|Тов = Документ.РасхНакл.Товар;
|Клиент = Документ.РасхНакл.Клиент;
|Группировка Клиент;
|Группировка Тов;
|Группировка Документ;
|"
;

Запрос.ИспользоватьГрафуОтбора("Клиент");
Если Запрос.Выполнить(ТекстЗапроса) = 0 Тогда
   Возврат;
КонецЕсли;

Организовать цикла получения данных из выборки, сформированной в результате работы метода Выполнить(), позволяет метод Группировка() (англоязычный синоним — Group()). Метод позиционирует в выборке очередную строку в порядке, определённом параметром <Группировка>. Нельзя использовать метод Группировка(), задавая в качестве параметра младшие группировки, не использовав предварительно этот метод для позиционирования по старшим группировкам. Старшинство группировок определяется порядком их следования в тексте запроса.

Синтаксис метода:

Группировка(<Группировка>, <Направление>)

где

  • <Группировка> — выражение, содержащее порядковый номер или имя группировки;
  • <Направление> — необязательный параметр — числовое выражение, определяющее направление выборки. Возможные значения:
    • 1 — выборка значений группировки по возрастанию (значение по умолчанию);
    • -1 (минус единица) — выборка значений группировки по убыванию.

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

Пример использования:

Процедура Сформировать()
   Перем Запрос, ТекстЗапроса;
   Если (Число(ДатаНач) = 0) ИЛИ (Число(ДатаКон) = 0) Тогда
      Предупреждение("Не задан период!");
      Возврат;
   КонецЕсли;
   
   Запрос = СоздатьОбъект("Запрос");
   ТекстЗапроса =
   "//{{ЗАПРОС(Сформировать)
   |с ДатаНач по ДатаКон;
   |Рез = ЖурналРасчетов.Зарплата.Результат;
   |Сотр = ЖурналРасчетов.Зарплата.Объект;
   |Группировка Сотр без групп;
   |Группировка ПериодЖурнала;
   |Функция Сум = Сумма(Рез);
   |"
   ;
   Если Сотрудник.Выбран() = 1 Тогда
      ТекстЗапроса = ТекстЗапроса + "Условие(Сотр = Сотрудник);";
   КонецЕсли;
   
   Если Запрос.Выполнить(ТекстЗапроса) = 0 Тогда
      Возврат;
   КонецЕсли;
   
   Таб = СоздатьОбъект("Таблица");
   
   Пока Запрос.Группировка("Сотр") = 1 Цикл
      
      Таб.ВывестиСекцию("Сотр<");
      Пока Запрос.Группировка("ПериодЖурнала") = 1 Цикл
         
         Таб.ВывестиСекцию("Мес");
      КонецЦикла;
      Таб.ВывестиСекцию("Сотр>");
   КонецЦикла;
   
   Таб.Опции(0, 0, 0, 0);
   Таб.ТолькоПросмотр(1);
   Таб.Показать("Результат", );
КонецПроцедуры

Выделить строки временного набора данных, которые являются группой справочника, позволяет метод ЭтоГруппа() (англоязычный синоним — IsItAGroup()). Возвращаемым значением метода является число 1, если текущая строка выборки (временного набора данных, сформированного в результате выполнения запроса) является группой справочника, или 0, если это обычный элемент справочника.

Синтаксис метода:

ЭтоГруппа(<ИмяГруппировки>)

где <ИмяГруппировки> — выражение, содержащее порядковый номер или имя группировки.

Пример использования:

Пока (Запр.Группировка("Товар") = 1) И (Запр.ЭтоГруппа("Товар") = 0) Цикл
    . . .
КонецЦикла;

Получить дату начала периода запроса позволяет метод НачалоПериода() (англоязычный синоним — BeginOfPeriod()). Если в тексте запроса указана одна из предопределённых группировок типа период ("Год", "Месяц", "День" и т.д.), то при обработке этой и вложенных в неё группировок метод НачалоПериода() будет возвращать начало периодов текущих значений этих группировок. Параметры у метода отсутствуют.

Пример использования:

ДатаНачала = Запрос.НачалоПериода();

Получить дату конца периода запроса позволяет метод КонецПериода() (англоязычный синоним — EndOfPeriod()). Если в тексте запроса указана одна из предопределённых группировок типа период ("Год", "Месяц", "День" и т.д.), то при обработке этой и вложенных в неё группировок метод КонецПериода() будет возвращать конец периодов текущих значений этих группировок. Параметры у метода отсутствуют.

Пример использования:

ДатаКонца = Запрос.КонецПериода();

Осуществить прямое позиционирование на запись в выборке по конкретным значениям группировок позволяет метод Получить() (англоязычный синоним — Get()). Количество параметров метода зависит от количества группировок в запросе. Можно пропускать значения одной или нескольких последних группировок, в этом случае метод позиционируется на запись, которая будет содержать итоговые значения для указанных группировок. Пропускаемые при вызове метода последние значения группировок должны заменяться запятыми. Если при вызове метода опущены все параметры, то выборка позиционируется на самое начало временного набора данных, на строку итогов. Возвращаемым значением метода является число 1, если запись найдена, или 0 – если нет.

После выполнения метода Получить() может осуществляться дальнейший обход выборки вызовами метода Группировка().

Синтаксис метода:

Получить(<ЗначениеГруппировки1>, ..., <ЗначениеГруппировкиN>)

где <ЗначениеГруппировки1>,, <ЗначениеГруппировкиN> — выражения, содержащие значения группировок запроса.

Пример использования:

Текст3апроса = "
| ...
|Группировка Должность;
|Группировка Категория;
| ...
|";

Если Запрос.Выполнить(ТекстЗапроса) = 0 Тогда
   Возврат;
КонецЕсли;
Если Запрос.Получить(ВыбДолжн, ВыбКатег) = 0 Тогда
   Если Запрос.Получить(ВыбДолжн, ) = 0 Тогда
       . . .
   КонецЕсли;
КонецЕсли;

Осуществить прямое позиционирование на начало выборки позволяет метод ВНачалоВыборки() (англоязычный синоним — ToSelectionBegin()). Например, если необходимо перейти на верхний уровень группировок, чтобы затем организовать проход группировки первого уровня (в любом направлении), следует использовать метод ВНачалоВыборки(). Возвращаемым значением метода является число 1, если операция выполнена успешно, или 0 – если нет. Параметры у метода отсутствуют.

Пример использования:

Текст3апроса = "
| ...
|Группировка Должность;
|Группировка Категория;
| ...
|";

Если Запрос.Выполнить(ТекстЗапроса) = 0 Тогда
   Возврат;
КонецЕсли;
Если Запрос.Получить(ВыбДолжн, ВыбКатег) = 0 Тогда
   Если Запрос.Получить(ВыбДолжн, ) = 0 Тогда
       . . .
   КонецЕсли;
КонецЕсли;
Запрос.ВНачалоВыборки();
Пока Запрос.Группировка(1, -1) Цикл
    . . .
КонецЦикла;

Получить значение поля упорядочивания из временной выборки запроса, не обращаясь к базе данных, позволяет метод ЗначениеУпорядочивания() (англоязычный синоним — OrderValue()).

Примечание: Если в тексте запроса для данной группировки не используется конструкция "Упорядочить по", то в этом случае действует упорядочивание по умолчанию:

  • для справочников — зависит от основного представления при описании справочника в Конфигураторе (код или наименование);
  • для документов — дата и время создания документа.

Синтаксис метода:

ЗначениеУпорядочивания(<Группировка>, <Упорядочив>)

где

  • <Группировка> — выражение, содержащее значение номера или имени группировки (номер работает быстрее);
  • <Упорядочив> — необязательный параметр. Порядковый номер параметра упорядочивания указанной группировки. Значение по умолчанию — 1.

Пример использования:

Текст3апроса = "
|ВидРаб = Документ.Наряд.ВидРаботы;
|Сотр = Документ.Наряд.Сотрудник;
|Группировка ВидРаб
|Упорядочить По ВидРаб.Код, ВидРаб.Стоимость;
|Группировка Сотр;
|";
 . . .

Запрос.ЗначениеУпорядочивания("ВидРаб", 2);

Запрос.ЗначениеУпорядочивания(2, 1);

Получить значение атрибута запроса по его имени позволяет метод ПолучитьАтрибут() (англоязычный синоним — SetAttrib()).

Синтаксис метода:

ПолучитьАтрибут(<ИмяАтрибута>)

где <ИмяАтрибута> — строковое выражение, содержащее имя любого атрибута запроса.

Пример использования:

Текст3апроса = "
|ВидРаб = Документ.Наряд.ВидРаботы;
|Сотр = Документ.Наряд.Сотрудник;
|Группировка ВидРаб
|Упорядочить По ВидРаб.Код, ВидРаб.Стоимость;
|Группировка Сотр;
|";
 . . .

Запрос.ПолучитьАтрибут("ВидРаб");

Запрос.ПолучитьАтрибут("Сотр");

Выгрузить результаты запроса в указанную таблицу значений позволяет метод Выгрузить() (англоязычный синоним — Unload()). Возвращаемым значением метода является число 1, если выгрузка произошла успешно, иначе – 0.

Синтаксис метода:

Выгрузить(<ТаблЗнач>, <Флаг>, <Итоги>)

где

  • <ТаблЗнач> — таблица значений, куда выгружаются результаты запроса;
  • <Флаг> — необязательный параметр. Число:
    • 0 — значения групп и функций (значение по умолчанию);
    • 1 — значения групп и функций, дополнительных переменных;
    • 2 — значения упорядочиваний групп и функций;
    • 3 — значения упорядочиваний групп и функций, дополнительных переменных;

    или строка типа "Товар(1), Товар(2), Товар, Склад, Приход, Расход", где Товар(1) — значение первого упорядочивания группировки "Товар" и т.д.

  • <Итоги> — необязательный параметр. Число:
    • 0 — итоги по группировкам не выводить;
    • 1 — итоги по группировкам выводить сверху (значение по умолчанию);
    • 2 — итоги по группировкам выводить снизу;
    • 3 — итоги по группировкам выводить сверху и снизу.

Пример использования:

Текст3апроса = "
| ...
|Группировка Должность;
|Группировка Категория;
| ...
|";

Если Запрос.Выполнить(ТекстЗапроса) = 0 Тогда
   Возврат;
КонецЕсли;
ТаблЗнач = Создать("ТаблицаЗначений");
Запрос.Выгрузить(ТаблЗнач, 0, 0);

Введение в язык запросов

Язык запросов предназначен для описания запросов к документам, справочникам, регистрам, журналам расчётов, планам счетов, бухгалтерским операциям и проводкам. Текст описания запроса передается методу Выполнить() в качестве параметра. В результате выполнения этого метода генерируется временный выходной набор данных, который в дальнейшем используется для заполнения формы отчёта.

Формат текста описания запроса

Текст описания запроса на языке запросов состоит из последовательности операторов. Концом оператора является символ «;» (точка с запятой). Операторы могут записываться в любом порядке, однако, следует помнить, что интерпретатор языка запросов однопроходный, следовательно, сначала следует описать переменную, и только потом её использовать в операторах Группировка, Функция или Условие.

Пример:

Текст3апроса =
"//({ЗАПРОС(РасчЛистки)
|  // Задаем интервал запроса
|Период с ДатаНач по ДатаКон;
|  // Определяем внутренние переменные
|Рез = ЖурналРасчетов.Зарплата.Результат;
|Расч = ЖурналРасчетов.Зарплата.ВидРасч;
|Дни = ЖурналРасчетов.Зарплата.Дни;
|Сотр = ЖурналРасчетов.Зарплата.Объект;
|  // Назначаем группировки
|Группировка Сотр без групп;
|Группировка Расч;
|  // Назначаем функции
|Функция Сум = Сумма(Рез);
|Функция Дней = Сумма(Дни);
|  // Назначаем условие
|Условие(Рез <> 0);
|"
;
 . . .

Как видно из вышеприведённого примера, в тексте запроса, также как и в остальном программном коде, допускается использование комментариев. Комментарий в тексте описания запроса начинается парой символов слэша (//) и заканчивается концом строки.

Соглашения и обозначения, используемые при описании языка

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

  • [] — в квадратные скобки заключаются необязательные синтаксические элементы;
  • []+ — в квадратные скобки со знаком «+» заключаются обязательные синтаксические элементы, которые могут использоваться один или более раз;
  • []* — в квадратные скобки со знаком «*» заключаются необязательные синтаксические элементы, которые могут использоваться один или более раз;
  • () — круглые скобки заключают в себе список параметров;
  • | — вертикальной линией разделяются синтаксические элементы, среди которых нужно выбирать один и только один.

Зарезервированные слова языка запросов

Ключевые слова — это слова, которые используются в языке запросов для обозначения встроенных операторов. Приведённые далее ключевые слова являются зарезервированными и не могут использоваться в качестве имён внутренних переменных описания запросов. Каждое ключевое слово имеет два представления — русское и английское. Английское представление является традиционным для языков программирования. Ключевые слова в русском и английском представлении могут свободно смешиваться в одном исходном тексте. Регистр букв ключевых слов не имеет значения, то есть они могут быть набраны в любом регистре, например: Функция, ФУНКЦИЯ, фУНКЦИЯ.

Ниже приведен полный список зарезервированных слов языка запросов в обоих представлениях:

  • Без (Without)
  • Год (Year)
  • Групп (Groups)
  • Группировка (Group)
  • День (Day)
  • Документ (Document)
  • И (And)
  • ИЛИ (Or)
  • Квартал (Quarter)
  • Когда (When)
  • Месяц (Month)
  • Неделя (Week)
  • НомерСтроки (LineNum)
  • Обрабатывать (Process)
  • ОбрабатыватьДокументы (ProcessDocuments)
  • ОбрабатыватьОперации (PrосessOperations)
  • Период (Period)
  • ПериодЖурнала (JournalPeriod)
  • По (By)
  • По (Till)
  • С (From)
  • СтрокаДокумента (DocumentLine)
  • Упорядочить (Order)
  • Условие (Condition)
  • Функция (Function)

Использование констант

В тексте запроса, также как и в остальном программном коде, допускается использование числовых и строковых констант (литералов), а также констант типа "Дата".

Числовая константа описывается следующей синтаксической диаграммой:

[+|-][0-9]+ | [0-9]*.[0-9]+

Пример числовых констант:

-17
43.712
.43842

Строковая константа — это строка, заключенная в двойные кавычки. Она не может быть многострочной.

Пример строковой константы:

"Это текстовая константа"

Константа типа "Дата" задаётся в виде строки, заключённой в одинарные кавычки, в формате 'ДД.ММ.ГГ' или 'ДД.ММ.ГГГГ'.

Примеры констант типа "Дата":

'21.05.96'
'25.09.1964'

Внутренние переменные

Внутренние переменные — это переменные, объявленные в тексте описания запроса. Именем переменной может быть любая последовательность букв, цифр и символов подчёркивания (_), начинающаяся с буквы или знака подчёркивания. Имена внутренних переменных не должны совпадать с зарезервированными словами языка запросов. Распознавание имён переменных, названий операторов, процедур и функций ведётся без учёта регистра букв.

Примеры имён переменных:

_43842
НачПериода

Примеры использования переменных:

Сотр = НовЗапрос.Сотр;
Кат = НовЗапрос.Кат;
ИТОГ = НовЗапрос.Итого;

Конкретизация переменной

Конкретизация переменной — это уточнение описания внутренней переменной, если это возможно в текущем контексте. Конкретизации переменной могут использоваться в языке запросов в операторах Группировка ... Упорядочить По и в качестве аргумента оператора Функция.

Синтаксис:

<ВнутренняяПеременная>[.<Путь>]+

где

  • <ВнутренняяПеременная> — идентификатор объявленной ранее внутренней переменной;
  • <Путь> — доступный атрибут внутренней переменной или конкретизации переменной (см. ниже «Атрибуты, доступные при описании внутренних переменных»).

Пример использования:

Запрос = СоздатьОбъект("Запрос");
ТекстЗапроса =
" //{{ЗАПРОС(ОбработкаДок)
|Период с '01.10.96' по '05.10.96';
|ОбрабатыватьДокументы Все;
|Тов = Справочник.Товары.ТекущийЭлемент, Документ.РасхНакл.Товар;
|  // используем конкретизацию внутренней переменной Тов
|Группировка Тов Упорядочить По Тов.Наименование;
|Группировка Документ;
|Группировка СтрокаДокумента;
|"
;

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

Внимание! Запрос не манипулирует величинами типа "Строка неограниченной длины".

Внешние переменные

Внешние переменные — это переменные из области видимости процедуры или функции программного модуля, в теле которого используется данный запрос. Внешние переменные в тексте описания запроса могут использоваться в операторах Период с и Условие.

Пример использования:

Перем ДатаНач, ДатаКон;

Процедура Сформировать()
   Если (Число(ДатаНач) = 0) ИЛИ (Число(ДатаКон) = 0) Тогда
      Предупреждение("Не задан период!");
      Возврат;
   КонецЕсли;
   
   Запрос = СоздатьОбъект("Запрос");
   ТекстЗапроса =
   "//{{ЗАПРОС(Сформировать)
   |  // используем внешние переменные ДатаНач и ДатаКон
   |с ДатаНач по ДатаКон;
   |Рез = ЖурналРасчетов.Зарплата.Результат;
   |Сотр = ЖурналРасчетов.Зарплата.Объект;
   |Группировка Сотр без групп;
   |Группировка ПериодЖурнала;
   |Функция Сум = Сумма(Рез);
   |"
   ;
   
   Если ВыбСотр.Выбран() = 1 Тогда
      ТекстЗапроса = ТекстЗапроса + "Условие(Сотр = ВыбСотр);";
   КонецЕсли;
   
   Если Запрос.Выполнить(ТекстЗапр) = 0 Тогда
      Возврат;
   КонецЕсли;
    . . .
КонецПроцедуры

Атрибуты, доступные при описании внутренних переменных

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

  • Документ (Document) — данные документов;
  • Справочник (Reference) — данные справочников;
  • Регистр (Register) — данные регистров;
  • ЖурналРасчетов (CalcJournal) — данные журналов расчёта;
  • Счет (Account) — данные счетов;
  • Операция (Operation) — данные бухгалтерских операций и проводок.

Эти названия являются первыми в пути описания переменных. В качестве атрибутов допускается использовать любые реквизиты, которые заданы для них в Конфигураторе в дереве метаданных (реквизиты для справочников, документов и журналов расчётов; измерения и ресурсы для регистров). Кроме этих атрибутов, разрешён так же доступ к следующим предопределённым атрибутам:

  • Доступные атрибуты объектов типа "Документ":
    • ВремяДок (DocTime) — время документа;
    • ДатаДок (DocDate) — дата документа;
    • НомерДок (DocNum) — номер документа;
    • НомерСтроки (LineNum) — номер строки документа;
    • ТекущийДокумент (CurDocument) — значение текущего документа.
  • Доступные атрибуты объектов типа "Справочник":
    • Родитель (Parent) — родитель элемента многоуровневого справочника;
    • Владелец (Owner) — владелец подчиненного справочника;
    • Код (Code) — код элемента справочника;
    • Наименование (Description) — наименование элемента справочника;
    • ТекущийЭлемент (CurItem) — значение текущего элемента справочника.
  • Доступные атрибуты объектов типа "Регистр":
    • НомерСтроки (LineNum) — номер строки документа, выполнившего движение регистра (в случае, когда в Модулях документов в конфигурации перед движением регистра использовали метод ПривязыватьСтроку);
    • ТекущийДокумент (CurDocument) — значение документа, выполнившего движение регистра.
  • Доступные атрибуты объектов типа "ПланСчетов":
    • БезКорреспонденций (IsSingle) — флаг того, что элемент плана счетов — забалансовый;
    • Валютный (IsCurrency) — флаг валютного учёта элемента плана счетов;
    • Код (Code) — код элемента плана счетов;
    • Количественный (IsAmount) — флаг количественного учёта элемента плана счетов;
    • Наименование (Description) — наименование элемента плана счетов;
    • ТекущийСчет (CurAccount) — значение текущего счета плана счетов.
  • Доступные атрибуты объектов типа "Операция":
    • ВремяОперации (OperTime) — время операции;
    • ДатаОперации (OperDate) — дата операции;
    • Содержание (Description) — содержание операции;
    • СуммаОперации (OperSum) — сумма операции;
    • ТекущийДокумент (CurDocument — значение документа создавшего операцию.
  • Доступные атрибуты объектов типа "Проводка":
    • ВалСумма (CurSum) — валютная сумма проводки (для счетов с валютным учётом);
    • Валюта (Currency) — валюта проводки;
    • Количество (Amount) — количество проводки (для счетов с количественным учётом);
    • КорСчет (CorAccount) — корреспондирующий счёт. Корреспондирующим счетом, для которого является Счет;
    • Сумма (Sum) — сумма проводки;
    • Счет (Account) — счет, для обработки корреспонденции. Корреспондирующим счётом, для которого является КорСчет.

Примеры использования атрибутов:

Запрос = СоздатьОбъект("Запрос");
ТекстЗапроса =
" //{{ЗАПРОС(Сформировать)
|Период с НачДата по КонДата;
|ДОКУМ = Документ.РасходнаяБН.ТекущийДокумент,
|   Документ.РасходнаяКредит.ТекущийДокумент,
|   Документ.РасходнаяНал.ТекущийДокумент,
|   Документ.РасходнаяРеализ.ТекущийДокумент,
|   Документ.Счет.ТекущийДокумент;
|Группировка ДОКУМ; //по документам
|"
;
Запрос = СоздатьОбъект("Запрос");
ТекстЗапроса =
"//{{ЗАПРОС(Печать)
|Товар = Справочник.Товары.ТекущийЭлемент;
|Группировка Товар Упорядочить по Товар.МинЗапас;
|"
;
Запрос = СоздатьОбъект("Запрос");
ТекстЗапроса =
"//{{ЗАПРОС(Сформировать)
|Период с НачДата по КонДата;
|ВидТоплива = Регистр.ПокупателиКолво.ВидыТоплива;
|Вес = Регистр.ПокупателиКолво.Кг;
|Покуп = Регистр.ПокупателиКолво.Покупатели;
|Док = Регистр.ПокупателиКолво.ТекущийДокумент;
|Ном = Регистр.ПокупателиКолво.НомерСтроки;
|Группировка ВидТоплива; //по измерению Регистра
|Группировка Док; // по документам, двигавшим Регистр
|Группировка Ном; // по номерам строк документов
|Функция ВсегоКолво = КонОст(Вес);
|Функция ПриходКолво = Приход(Вес);
|Условие(Покуп = ВыбПокупатель);
|"
;

Правила объявления внутренних переменных

Внутренние переменные используются в тексте запроса для образования ссылок на объекты конфигурации, чтобы использовать их при построении таких операторов запроса, как Группировка, Функция, Условие.

Синтаксис объявления внутренней переменной:

<ИмяПеременной> = <ОписаниеПеременной> [, <ОписаниеПеременной>]+;

где

  • <ИмяПеременной> — имя объявляемой внутренней переменной описания запроса;
  • <ОписаниеПеременной> — ссылка, указывающая на доступный в языке запросов атрибут документа, справочника, регистра или журнала расчётов (см. выше «Атрибуты, доступные при описании внутренних переменных»).

В объявлении внутренней переменной можно указывать несколько вариантов описания переменной. Все описания должны указывать на один и тот же тип данных (число, строку, справочник или документ). Переменной, указывающей на разные справочники или документы, присваивается тип данных "Справочник неопределённого вида" или "Документ неопределённого вида" соответственно.

Например, можно определить внутреннюю переменную:

Товар = Документ.Перемещение.Товар, Документ.Расходная.Товар;

и использовать её для создания группировки. Такой состав внутренней переменной как бы дает группировке задание — просмотреть все документы видов Перемещение и Расходная и выбрать все товары, встречающиеся либо в документах вида Перемещение, либо в документах Расходная.

Еще пример. Допустим, у нас есть регистр Взаиморасчеты и регистр Кредиты, и в том и в другом есть измерение Клиент. Определяем внутреннюю переменную:

Должник = Регистр.Взаиморасчеты.Клиент, Регистр.Кредиты.Клиент;

Если использовать такую внутреннюю переменную для образования группировки, то она будет означать следующее: пройти по регистру Взаиморасчеты и по регистру Кредиты, вычислить заданные в запросе функции и выбрать значения клиентов, для которых значения хотя бы одной функции будет ненулевой. Здесь мы видим, что формирование запроса по регистрам имеет некоторые особенности (обязательно наличие функций, причём их вычисленные значения должны быть отличны от нуля, только в этом случае найденные объекты включаются во временный набор данных формируемый запросом).

Внимание! Если при описании внутренней переменной указать на разные типы данных, например, на "Справочник" и на "Документ", то это просто вызовет сообщение об ошибке. Например, следующее определение внутренней переменной будет ошибочным:

ААА = Справочник.Товары.ТекущийЭлемент, Документ.Счет.ТекущийДокумент;   

Однако допускается в описании внутренней переменной указание на разные справочники либо на разные документы. Переменной, указывающей на разные справочники или документы, присваивается тип данных "Справочник неопределённого вида" или "Документ неопределённого вида" соответственно. Например, правомерно задать такую внутреннюю переменную:

Парам = Документ.Счет.Клиент, Документ.Счет.Фирма;

(Здесь предполагается, что в контексте конфигурации, реквизиты Клиент и Фирма — это элементы справочников). Если использовать такую внутреннюю переменную для построения группировки, то она будет означать следующее: пройти по документам Счет и выбрать значения клиентов и фирм, встречающихся в них (и, например, упорядочить эти элементы по наименованию). Как интерпретировать результаты полученной выборки при таком запросе — будет зависеть от контекста поставленной задачи.

Особенности описания внутренних переменных для типов "Операция" и "Проводка"

В языке запросов описание внутренних переменных для агрегатных типов данных типа "Операция" и "Проводка" начинается со слова «Операция» вне зависимости от того, будет ли обращение к бухгалтерским операциям или к проводкам. Описание переменной определяется следующим образом:

Операция.(
   <Реквизиты0перации>
   |  <ПредРеквОпераций>
   |  <РеквизитыПроводок>
   |  <ПредРеквПроводок>
   |  Дебет. ( Счет | <Субконто> )
   |  Кредит. ( Счет | <Су6конто> )
   |  Субконто.<ВидСубконто>
   |  КорСубконто.<ВидСубконто>
)

где

  • <Реквизиты0перации> — реквизиты операции, объявленные в метаданных;
  • <ПредРеквОпераций> — предопределённые реквизиты операций;
  • <РеквизитыПроводок> — реквизиты проводок, объявленные в метаданных;
  • <ПредРеквПроводок> — предопределённые реквизиты проводок;
  • <ВидСубконто> — идентификатор вида субконто.

Применение слов «Дебет», «Кредит» в описании переменных позволяют оперировать дебетовой и кредитовой частями проводки, такими как счёт и вид субконто. Применение слов «Субконто» и «КорСубконто» в описании переменных позволяют оперировать как субконто, так и корреспондирующим субконто.

Пример:

Сум = Операция.Сумма;
Сч = Операция.Дебет.Счет, Операция.Кредит.Счет;

О дополнительных именах доступа

Несколько слов о дополнительных именах доступа к стандартной информации, которые определены в языке запросов. Речь идёт о конструкции ТекущийЭлемент для справочников и ТекущийДокумент для документов и регистров (не надо путать эти конструкции языка запросов с одноимёнными методами встроенного языка, хотя их смысл во многом совпадает).

Для справочников использование конструкции ТекущийЭлемент в описании внутренней переменной означает выборку элемента справочника как такового (целиком всей записи справочника).

Аналогично при работе с документами, использование конструкции ТекущийДокумент в описании внутренней переменной, означает выборку документа как такового (целиком всего документа как объекта конфигурации). Сравните два примера, приведённых ниже.

Пример 1. Здесь нас интересуют товары, встречающиеся в документах:

ТОВАР = Документ.РасходнаяБН.Товар, 
   Документ.РасходнаяКредит.Товар,
   Документ.РасходнаяНал.Товар,
   Документ.РасходнаяРеализ.Товар,
   Документ.Счет.Товар;

Пример 2. Здесь нас интересуют сами документы указанных видов как таковые:

ДОКУМ = Документ.РасходнаяБН.ТекущийДокумент, 
   Документ.РасходнаяКредит.ТекущийДокумент,
   Документ.РасходнаяНал.ТекущийДокумент,
   Документ.РасходнаяРеализ.ТекущийДокумент,
   Документ.Счет.ТекущийДокумект;

Использование для документов конструкции НомерСтроки в описании внутренней переменной, означает выборку номеров строк документов (не самих строк, а чисел, обозначающих номера строк в документе):

СТРОКА = Документ.РасходнаяБН.НомерСтроки;

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

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

Пример:

Запрос = СоздатьОбъект("Запрос");
ТекстЗапроса =
"//{{ЗАПРОС(Сформировать)
|Период с НачДата по КонДата;
|ВидТоплива = Регистр.ПокупателиКолво.ВидыТоплива;
|Покуп = Регистр.ПокупателиКопво.Покупатели;
|Док = Регистр.ПокупателиКолво.ТекущийДокумент;
|Ном = Регистр.ПокупателиКолво.НомерСтроки;
|Вес = Регистр.ПокупателиКолво.Кг;
|Группировка ВидТоплива; // по измерению Регистра
|Группировка Док; //по документам, двигавшим Регистр
|Группировка Ном; // по номерам строк документов
|Функция ВсегоКолво = КонОст(Вес);
|Функция ПриходКолво = Приход(Вес);
|Условие(Покуп = Покупат);
|"
;

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

В программном модуле конфигурации (т.е. вне текста запроса) существует доступ (там, где это имеет смысл) к значениям всех объявленных в тексте запроса внутренних переменных, даже тех, которые не участвуют ни в группировках, ни в функциях. Другими словами, если объявленная в тексте запроса внутренняя переменная не задействована в запросе ни в группировке, ни в функции, ни в условии, данная внутренняя переменная всё же присутствует в запросе.

Операторы языка запросов

Установить интервал дат формирования запроса позволяет оператор Период С ... По (англоязычный синоним — Period From ... Till). Если в описании запроса оператор Период С ... По опущен, то интервал дат формирования запроса устанавливается в точку актуальности итогов (ТА) (или на рабочую дату, если не установлена компонента «Оперативный учет»), запрос формируется только на этот момент времени.

Использование данного оператора актуально только в том случае, если запрос строится для выборки данных по регистрам, журналам расчётов и/или документам. Здесь указывается, в каком интервале выбирать движения регистров и/или подборку документов. При выполнении запроса только по справочникам эта секция не играет никакой роли.

Синтаксис оператора:

[[Период] С <Дата>|<ВнешПеременная> [По <Дата>|<ВнешПеременная>];]

где

  • <Дата> — константа типа "Дата", "Документ" или позиция документа;
  • <ВнешПеременная> — внешняя переменная типа "Дата", "Документ" или позиция документа. Если указан документ, то за момент времени принимается дата и время документа;
  • По — добавочное ключевое слово для связки первой части команды со второй, необязательной частью.

Параметрами оператора Период С являются значения момента времени ("Дата", "Документ" или позиция документа) начала и конца временного интервала. Следует особо обратить внимание, что если интервал задаётся с точностью до даты, то интервал времени считается от начала даты нижней границы интервала до конца даты верхней границы интервала. Если вторая часть оператора после ключевого слова По пропущена или значение второго параметра команды равно нулю, то интервал времени применяется от начального момента времени до ТА (или по рабочую дату, если не установлена компонента «Оперативный учет»). Это особенно важно при формировании запросов по регистрам, так как запрос по регистрам может строиться от любой даты в прошлом до ТА. Поэтому, если вы укажете в запросе верхнюю границу интервала большей или равной дате ТА, то программа, скорее всего, сообщит «Не могу рассчитать регистры за ТА» (поскольку время ТА лежит где то в пределах даты, а запрос пытается учесть всю дату в целом). Поэтому при формировании текста запроса следует вставлять дополнительную проверку типа той, что приведена в следующем примере:

Запрос = СоздатьОбъект("Запрос");
ТекстЗапроса =
 . . .
|Счет = Регистр.Cash.Счет;
|Статья = Регистр.Cash.Статья;
|СуммаЭквивалента2 = Регистр.Cash.СуммаЭквивалента2;
|СуммаЭквивалента1 = Регистр.Cash.СуммаЭквивалента1;
 . . .

Если ДатаКонца >= ПолучитьДатуТА() Тогда
   ТекстЗапроса = ТекстЗапроса + "Период с ДатаНачала;";
Иначе
   ТекстЗапроса = ТекстЗапроса + "Период с ДатаНачала по ДатаКонца;";
КонецЕсли;
Если Запрос.Выполнить(ТекстЗапроса) = 0 Тогда
   Возврат;
КонецЕсли;

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

Применение конструкции С ... По ... приводит к тому, что выборка записей из журнала расчётов проводится по времени действия записей журнала расчётов, определяемых реквизитами журнала расчётов ДатаНачала и ДатаОкончания, а не временем их ввода в журнал.

Примечание: Работа запроса с журналами расчётов, с использованием конструкции Период С ... По ..., аналогична выборке записей в журнале расчётов, организуемой при помощи метода журнала расчётов ВыбратьПериод(). С другой стороны, запрос, использующий конструкцию С ... По ..., аналогичен выборке, организуемой при помощи метода журнала расчётов ВыбратьЗаписи().

Пример 1:

Процедура РасчЛистки()
   Перем Запрос, Флаг;
   Перем ДатаНач, ДатаКон;
   ЖР = СоздатьОбъект("ЖурналРасчетов.Зарплата");
   ДатаНач = ЖР.НачалоТекущегоПериода();
   ДатаКон = ЖР.КонецТекущегоПериода();
   
   Запрос = СоздатьОбъект("Запрос");
   Флаг = Запрос.Выполнить(
   "//{{ЗАПРОС(РасчЛистки)
   |Период С ДатаНач По ДатаКон; // выборка по расчетным периодам!
   |Рез = ЖурналРасчетов.Зарплата.Результат;
   |Расч = ЖурналРасчетов.Зарплата.ВидРасч;
   |Дни = ЖурналРасчетов.Зарплата.Дни;
   |Сотр = ЖурналРасчетов.Зарплата.Объект;
   |Группировка Сотр без групп;
   |Группировка Расч;
   |функция Сум = Сумма(Рез);
   |функция Дней = Сумма(Дни);
   |Условие(Рез о 0);
   |"
   );
    . . .
КонецПроцедуры;

Пример 2:

Запрос = СоздатьОбъект("Запрос");

ТекстЗапроса =
"//{{ЗАПРОС(Сформировать)
|С ДатаНач По ДатаКон;
|Рез = ЖурналРасчетов.Зарплата.Результат;
|Сотр = ЖурналРасчетов.Зарплата.Объект;
|ПЖ = ЖурналРасчетов.Зарплата.ПериодРегистрации;
|Группировка Сотр без групп;
|Группировка ПЖ;
|Функция Сум = Сумма(Рез);
|"
;
Флаг = Запрос.Выполнить(ТекстЗапроса);
 . . .

Назначить режим обработки документов в запросе позволяет оператор ОбрабатыватьДокументы (англоязычный синоним — ProcessDocuments). В операторе указывается, какими документами должен оперировать запрос: непроведёнными (NonTransacted), проведёнными (Transacted) или теми и другими (All). По умолчанию в запросе обрабатываются только проведённые документы.

Синтаксис оператора:

ОбрабатыватьДокументы [Непроведенные|Проведенные|Все];

где Непроведенные, Проведенные, Все — указание, какие документы следует обрабатывать.

Пример:

Запрос = СоздатьОбъект("Запрос");
ТекстЗапроса =
"//{{ЗАПРОС(ОбработкаДок)
|Период с '01.10.96' по '05.10.96';
|ОбрабатыватьДокументы Все;
|Тов = Справочник.Товары.ТекущийЭлемент, Документ.РасхНакл.Товар;
|Группировка Тов упорядочить по Тов.Наименование;
|Группировка Документ;
|Группировка СтрокаДокумента;
|"
;
Если Запрос.Выполнить(ТекстЗапроса) = 0 Тогда
   Возврат;
КонецЕсли;

Назначить режим обработки бухгалтерских операций в запросе позволяет оператор ОбрабатыватьОперации (англоязычный синоним — ProcessOperations). В операторе указывается, какими операциями должен оперировать запрос: с включенными проводками (On), с выключенными проводками (Off) или теми и другими (All). По умолчанию в запросе обрабатываются только операции с включенными проводками.

Синтаксис оператора:

ОбрабатыватьОперации [Включенные|Выключенные|Все];

где Включенные, Выключенные, Все — указание, какие операции следует обрабатывать.

Пример:

Запрос = СоздатьОбъект("Запрос");
ТекстЗапроса =
"//{{ЗАПРОС(ОбработкаОпер)
|Период с '01.10.96' по '05.10.96';
|ОбрабатыватьОперации Все;
|Опер = Операция.ТекущийДокумент;
|Группировка Опер;
|"
;
Если Запрос.Выполнить(ТекстЗапроса) = 0 Тогда
   Возврат;
КонецЕсли;

Назначить режим обработки помеченных на удаление объектов в запросе позволяет оператор Обрабатывать (англоязычный синоним — Process). В операторе указывается, какими объектами должен оперировать запрос: не помеченными на удаление (NonMarkedOnRemoving), помеченными на удаление (MarkedOnRemoving) или теми и другими (All). По умолчанию в запросе обрабатываются все объекты.

Синтаксис оператора:

Обрабатывать [ПомеченныеНаУдаление|НеПомеченныеНаУдаление|Все];

где ПомеченныеНаУдаление, НеПомеченныеНаУдаление, Все — указание, какие объекты следует обрабатывать.

Пример:

Запрос = СоздатьОбъект("Запрос");
ТекстЗапроса =
"//{{ЗАПРОС(Обработка)
|Период с '01.10.96' по '05.10.96';
|Обрабатывать НеПомеченныеНаУдаление;
|Товар = Справочник.Товар.ТекущийЭлемент;
|Группировка Товар упорядочить по Товар.Наименование;
|"
;
Если Запрос.Выполнить(ТекстЗапроса) = 0 Тогда
   Возврат;
КонецЕсли;

Вычислить указанный тип функции и присваивает её значение внутренней переменной позволяет оператор Функция (англоязычный синоним — Function).

Синтаксис оператора:

Функция <ИмяФункции> = <ТипФункции> (<Параметр>|<УточненныйПараметр>) [Когда (<Условие>)];

где

  • <ИмяФункции> — имя, которое присваивается функции. По этому имени можно в дальнейшем обращаться к значению вычисленной функции из вызывающего программного модуля как к атрибуту запроса. Данную внутреннюю переменную заранее объявлять не нужно. Она фактически неявно объявляется в операторе Функция;
  • <ТипФункции> — ключевое слово одной из встроенных функций языка (см. список типов ниже);
  • <Параметр> — имя объявленной ранее внутренней переменной, значение которой используется как параметр встроенной функции. В функциях Сумма, Среднее, Максимум, Минимум в качестве данного параметра возможно использование арифметического выражения в терминах встроенного языка «1С:Предприятие»;
  • <УточненныйПараметр> — конкретизация объявленной ранее внутренней переменной, значение которой используется как аргумент встроенной функции;
  • Когда (англ. When) — необязательное добавочное ключевое слово, использование которого в команде означает, что вычисление функции следует производить только при условии, когда заданное логическое выражение <Условие> истинно;
  • <Условие> — логическое выражение встроенного языка «1С:Предприятие». В логическом выражении могут участвовать как внутренние, так и внешние переменные запроса. Используется только после ключевого слова Когда.

Типы применяемых функций предопределены и могут быть следующими:

  • Сумма (Sum) — вычисляет сумму выбранных по запросу значений параметра*;
  • Среднее (Avg) — вычисляет среднее из выбранных по запросу значений параметра;
  • Минимум (Min) — вычисляет минимум из выбранных по запросу значений параметра;
  • Максимум (Мах) — вычисляет максимум из выбранных по запросу значений параметра;
  • Счётчик (Count) — подсчитывает количество записей, вошедших в выборку;
  • НачОст (BegRest) — вычисляет начальный остаток для выбранных по запросу значений параметра**;
  • КонОст (EndRest) — вычисляет конечный остаток для выбранных по запросу значений параметра**;
  • Приход (Debit) — вычисляет приход для выбранных но запросу значений параметра**;
  • Расход (Credit) — вычисляет расход для выбранных по запросу значений параметра**;
  • СНД (IDB) — вычисляет сальдо начальное дебетовое для выбранных по запросу значений параметра***;
  • СКД (FDB) — вычисляет сальдо конечное дебетовое для выбранных по запросу
    значений параметра***;
  • СНК (ICD) — вычисляет сальдо начальное кредитовое для выбранных по запросу значений параметра***;
  • СКК (FCD) — вычисляет сальдо конечное кредитовое для выбранных по запросу значений параметра***;
  • ДО (TD) — вычисляет дебетовые обороты для выбранных по запросу значений параметра***;
  • КО (TC) — вычисляет кредитовые обороты для выбран
    ных по запросу значений параметра***;
  • КорДО (CorTD) — вычисляет дебетовые обороты между корреспондирующим счетам или субконто для выбранных по запросу значений параметра****;
  • КорКО (CorTC) — вычисляет кредитовые обороты между корреспондирующим счетам или субконто для выбранных по запросу значений параметра****;

Примечания:

* Для ресурсов оборотных регистров допускается вызывать только тип функции "Сумма".

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

*** Функции "СНД", "СНК", "СКД", "СКК", "ДО", "КО" можно использовать только с реквизитами проводки: Сумма, Количество или ВалСумма.

**** Функции "КорДО" и "КорКО" можно использовать только с реквизитами проводки: Сумма, Количество или ВалСумма. Функции накапливают значения только тогда, когда в запросе есть обращение к реквизитам проводок Счет, КорСчет, Субконто или КорСубконто.

Примечание 5: В программном модуле, где используется запрос, <ИмяФункции> будет являться атрибутом запроса. При помощи данного атрибута можно обращаться к значению вычисленной в запросе функции.

Примечание 6: В функциях "Сумма", "Среднее", "Максимум", "Минимум" в качестве аргумента возможно использование арифметического выражения в терминах встроенного языка.

Пример:

 . . .
|КолВо = Документ.ВидДокумента.Количество;
|Цена = Документ.ВидДокумента.Цена;
|Функция Сум = Сумма(КолВо * Цена);
|Функция Макс = Максимум(Окр(КолВо) * Окр(Цена));
|Функция Средн = Среднее(ФункцияОпределеннаяВМодуле(КолВо, Цена));
 . . .

Другой пример:

Запрос = СоздатьОбъект("Запрос");
ТекстЗапроса =
"//ЗАПРОС(Функции)
|Период с ДатаНач по ДатаКон;
|Оклад = Справочник.Сотрудники.Оклад;
|Подр = Справочник.Сотрудники.Подразделение;
|Ктг = Справочник.Сотрудники.Категория;
|Группировка Подр без групп;
|Группировка Ктг без групп;
|Функция Всего = Сумма(Оклад);
|Условие((Ктг.Выбран() = 1) И (Подр.Выбран() = 1));
|"
;
Если Запрос.Выполнить(ТекстЗапроса) = 0 Тогда
   Возврат;
КонецЕсли;
 . . .
Итог = Запрос.Всего;
 . . .

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

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

При создании в тексте запроса внутренней переменной, которую вы предполагаете использовать в качестве параметра оператора Функция, надо учитывать, что тип этой внутренней переменной должен быть "Число", так как функции в языке запросов обрабатывают только числовые значения.

В тексте запроса, при описании оператора Функция можно использовать необязательное ключевое слово Когда, использование которого в операторе означает, что вычисление функции следует производить только при условии, что значение логического выражения, заданного в параметре ключевого слова является "Истина". Синтаксис применяемого логического выражения полностью аналогичен синтаксису разрешённому к применению в операторах Условие.

Следует понимать, что не все функции внутри конкретной группировки запроса могут иметь чётко интерпретируемый смысл. Например, для группировки по документу движения регистра следующие функции

|Функция ПрихКол = Приход(Количество);
|Функция РасхКол = Расход(Количество);

имеют четкий смысл — приращения, сделанные документом при движении регистра. С другой стороны, в той же группировке следующие функции

|Функция НачКол = НачОст(Количество);
|Функция КонКол = КонОст(Количество);

явно не имеют смысла (в запросах по регистрам, обычно задают период запроса при помощи оператора Период C. Функция "НачКол" в данном примере должна по смыслу показывать остаток ресурса Количество на начальную дату запроса. Внутри группировки по документу вопрос: «Какой начальный остаток ресурса на дату 10.01.97?» по документу, проведённому, например, 13.01.97, не имеет смысла). Поэтому в таких ситуациях функция будет иметь нулевое значение.

Пример:

Запрос = СоздатьОбъект("Запрос");
ТекстЗапроса =
"//ЗАПРОС(Функции)
|Период с ДатаОтчета;
|Товар = Регистр.КвотыТоваров.Товар;
|Отдел = Регистр.КвотыТоваров.Отдел;
|Сотрудник = Регистр.КвотыТоваров.Сотрудник;
|Партнер = Регистр.КвотыТоваров.Партнер;
|Док = Регистр.КвотыТоваров.ТекущийДокумент;
|Количество = Регистр.КвотыТоваров.КвотаТовара;
|Группировка Товар;
|Группировка Отдел;
|Группировка Сотрудник;
|Группировка Партнер;
|Группировка Док;
|Функция НачКол = НачОст(Количество);
|Функция ПрихКол = Приход(Количество);
|Функция РасхКол = Расход(Количество);
|Функция КонКол = КонОст(Количество);
|// Следующие Функции вычисляем только при определенных
|// условиях, чтобы получить отфильтрованные итоги
|Функция ПрихКолТов = Приход(Количество) Когда (Док.ФлагТовара = 1);
|Функция РасхКолТов = Расход(Количество) Когда (Док.ФлагТовара = 1);
|Функция ПрихКолОтд = Приход(Количество) Когда (Док.ФлагОтдела = 1);
|Функция РасхКолОтд = Расход(Количество) Когда (Док.ФлагОтдела = 1);
|Функция ПрихКолСотр = Приход(Количество) Когда (Док.ФлагСотрудника = 1);
|Функция РасхКолСотр = Расход(Количество) Когда (Док.ФлагСотрудника = 1);
|"
;

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

Задать способ группировки информации и порядок её упорядочивания в запросе позволяет оператор Группировка (англоязычный синоним — Group). От способа группировки информации и порядка её упорядочивания в запросе зависит последующий порядок её выборки.

Синтаксис оператора:

Группировка <ИмяГруппировки>|<ПредопредГруппировка> [Упорядочить по <Порядок>[, <Порядок&#gt;]*]
            [Без Упорядочивания][Без Групп][Все [ВошедшиеВЗапрос]];

где

  • <ИмяГруппировки> — имя объявленной ранее внутренней переменной, по значению которой устанавливается порядок выборки. По этому имени можно в дальнейшем обращаться к значению группировки из вызывающего программного модуля как к атрибуту запроса;
  • <ПредопредГруппировка> — ключевое слово одной из встроенных предопределенных группировок языка запросов (см. список ниже). По этому имени можно будет обращаться к значению группировки из вызывающего программного модуля;
  • Упорядочить по (англ. Order By) — необязательное добавочное ключевое слово. Параметры, следующие за данным ключевым словом, определяют упорядочивание строк в группировке. По умолчанию документы упорядочиваются по дате и времени документов, справочники — по коду или наименованию, в зависимости от основного представления, заданного при описании справочника в Конфигураторе;
  • <Порядок> — используется только после ключевого слова Упорядочить по. Конкретизация внутренней переменной <ИмяГруппировки>, значение которой является параметром упорядочивания строк в группировке. Кроме того, в данном параметре можно использовать имя функции, объявленной в этом же запросе в операторе Функция;
  • Без Упорядочивания (англ. Without Order) — необязательное добавочное ключевое слово, которое преследует цель уменьшения времени формирования запроса, при условии, что ни упорядочивание, ни значения упорядочивания при использовании данного запроса не нужны;
  • Без Групп (англ. Without Groups) — необязательное добавочное ключевое слово, использование которого назначает вывод в запрос только простых элементов справочников (исключая группы). Используется только для группировок, построенных на основе внутренней переменной типа "Справочник";
  • Все (англ. All) — необязательное добавочное ключевое слово, действие которого зависит от типа внутренней переменной, на основе которой построена группировка. Используется только для группировок, построенных на основе внутренней переменной типа "Справочник", или для предопределённых группировок, задающих временной интервал (Год, Месяц, Квартал, Неделя, День). Для предопределённых временных группировок подразумевается, что в запрос будут включены любые значения данных (в том числе нулевые) в каждый заданный момент времени с даты начала запроса по дату конца запроса (интервал задаётся оператором Период С...). Для группировок по справочникам подразумевается, что в запрос будут включены любые значения данных (в том числе нулевые) для каждого допустимого элемента справочника;
  • ВошедшиеВЗапрос (англ. IncludedInQuery) — необязательное добавочное ключевое слово действие которого уточняет предыдущее ключевое слово Все. Использование данного слова подразумевает, что в каждую строку запроса будут включены значения данных (в том числе нулевые), для которых есть ненулевое значение хотя бы в одной строке запроса.

Предопределённые группировки могут быть следующими:

  • Документ (Document) — позволяет детализацию до каждого документа;
  • СтрокаДокумента (DocumentLine) — позволяет детализацию до каждой строки табличной части каждого документа;
  • День (Day), Неделя (Week), Месяц (Month), Квартал (Quarter), Год (Year) — группировки по дате, дают возможность накапливать значения по документам за конкретный период (на каждый день, неделю, месяц и т.д.). В запросе может присутствовать несколько группировок такого типа.

Замечание: В программном модуле, где используется запрос, имя <ИмяГруппировки> (или <ПредопредГруппировка>) будет являться атрибутом запроса. Кроме того, это имя используется в качестве параметра метода запросов Группировка().

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

Несколько операторов Группировка, следующих друг за другом в описании запроса, создают вложенные группировки запроса. Первая группировка — самая старшая, в неё будет вложена следующая группировка, далее будет вложена следующая и т.д. По смыслу, вложенная группировка осуществляет более детальный просмотр объекта внешней группировки. Например, если во внешней группировке мы просматриваем регистр, то во вложенной группировке можно просмотреть документы движений этого регистра, а далее можно сформировать группировку по номерам строк этих документов.

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

По умолчанию, документы упорядочиваются в группировке по дате и времени документов, элементы справочников — в зависимости от основного представления, заданного при описании справочника в Конфигураторе (код или наименование). Однако критерий упорядочивания в группировке можно установить при помощи необязательного ключевого слова Упорядочить по. Параметры, следующие за данным ключевым словом, определяют упорядочивание строк в группировке.

С параметром упорядочивания связан специальный метод для доступа к значениям объекта "Запрос". Речь идет об использовании метода ЗначениеУпорядочивания(). В программном модуле, после того как запрос уже сформирован, мы можем при помощи этого метода получить значение поля упорядочивания из временного набора данных, не обращаясь к базе данных. Например, если у нас в запросе была группировка "Товар", а нам для формирования некоторого отчёта нужны значения наименований товаров, то эти наименования товаров можно получить двумя способами:

Наим = Запрос.Товар.Наименование;



Наим = Запрос.ЗначениеУпорядочивания("Товар", 1);

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

Пример:

Процедура Группировки()
   Перем Запрос, ТекстЗапроса;
   Перем ДатаНач, ДатаКон;
   ЖР = СоздатьОбъект("ЖурналРасчетов.Зарплата");
   ДатаНач = ЖР.НачалоТекущегоПериода();
   ДатаКон = ЖР.КонецТекущегоПериода();
   
   Запрос = СоздатьОбъект("Запрос");
   ТекстЗапроса =
   "//{{ЗАПРОС(Группировки)
   |Период с ДатаНач по ДатаКон;
   |Рез = ЖурналРасчетов.Зарплата.Результат;
   |Расч = ЖурналРасчетов.Зарплата.ВидРасч;
   |Дни = ЖурналРасчетов.Зарплата.Дни;
   |Сотр = ЖурналРасчетов.Зарплата.Объект;
   |Группировка Сотр без групп;
   |Группировка Расч;
   |Функция Сум = Сумма(Рез);
   |Функция Дней = Сумма(Дни);
   |Условие(Рез о 0);
   |"
   ;
   
   Если Запрос.Выполнить(ТекстЗапроса) = 0 Тогда
      Возврат;
   КонецЕсли;
   
   Таб = СоздатьОбъект("Таблица");
   Пока Запрос.Группировка("Сотр") = 1 Цикл
      
      Таб.ВывестиСекцию("Сотр");
      Пока Запрос.Группировка("Расч") = 1 Цикл
         
         Таб.ВывестиСекцию("Расч");
      КонецЦикла;
   КонецЦикла;
   Таб.Опции(0, 0, 0, 0);
   Таб.ТолькоПросмотр(1);
   Таб.Показать("Результат", );
КонецПроцедуры

Увеличить скорости выполнения запроса, если итоговые записи при использовании запроса не нужны, позволяет оператор Без итогов (англоязычный синоним — Without Totals). Данный оператор языка запросов, даёт возможность не накапливать итоги по группировкам. Использовать данный оператор в тексте запроса имеет смысл, когда запрос строится не для формирования сложного отчёта, а например, для простой выборки значений из информационной базы для последующей их обработки.

В случае применения данного оператора в тексте запроса, при обходе результатов запроса применяется только один цикл обхода, используя метод объекта "Запрос" Группировка() без параметра.

Пример:

Запрос = СоздатьОбъект("Запрос");
Текст3апроса = "
 . . .
|Группировка Товар;
|Группировка Склад;
|Без Итогов;
|"
;
Если Запрос.Выполнить(ТекстЗапроса) = 1 Тогда
   Возврат;
КонецЕсли;

Пока Запрос.Группировка() = 1 Цикл
    . . .
КонецЦикла;

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

Задать условие включения информации в запрос позволяет оператор Условие (англоязычный синоним — Condition). Если указанное в качестве параметра логическое выражение истинно, то информация включается в запрос, иначе нет.

Синтаксис оператора:

Условие(<ЛогическоеВыражение>);

где <ЛогическоеВыражение> — логическое выражение встроенного языка «1С:Предприятие». В логическом выражении могут участвовать как внутренние, так и внешние переменные запроса, то есть переменные программного модуля, доступные в процедуре, использующей запрос.

Пример:

ТекстЗапроса =
"//{{ЗАПРОС(Одинарный)
|Период с ДатаНачала по ДатаКонец;
|Оклад = Справочник.Сотрудники.Оклад;
|Ктг = Справочник.Сотрудники.Категория;
|Группировка Ктг без групп;
|Функция Всего = Сумма(Оклад);
|Условие(Ктг.Выбран() = 1);   // только для тех сотрудников
| // у кого заполнен реквизит Категория
|"
;

Далее в нижеприведённом примере показан отрывок текста процедуры, в которой формируется некоторый отчёт, причём переменные ВыбТовар, ВыбОтдел, ВыбСотрудник являются реквизитами диалога отчёта, значит, они доступны в программном модуле, поэтому могут быть использованы в логическом выражении оператора Условие(). В данном примере операторы Условие() использованы для фильтрации в запросе только выбранных значений параметров отчёта:

Запрос = СоздатьОбъект("Запрос");
ТекстЗапроса =
"//{{ЗАПРОС(Квоты)
|Товар = Регистр.КвотыТоваров.Товар;
|Отдел = Регистр.КвотыТоваров.Отдел;
|Сотрудник = Регистр.КвотыТоваров.Сотрудник;
|Партнер = Регистр.КвотыТоваров.Партнер;
|Количество = Регистр.КвотыТоваров.КвотаТовара;
|Группировка Товар;
|Группировка Отдел;
|Группировка Сотрудник;
|Группировка Партнер;
|Функция Кол_во = КонОст(Количество);
|Условие(Товар.ПринадлежитГруппе(ВыбТовар) = 1);
|Условие(Отдел = ВыбОтдел);
|Условие(Сотрудник = ВыбСотрудник.Сотрудник);
|"
;

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

В параметре оператора Условие(), в принципе, можно записывать логические выражения любой сложности (по правилам встроенного языка «1С:Предприятие»), используя любые логические операторы (>, <, =, >=, <>, И, ИЛИ, НЕ и др.), при этом в качестве операндов могут участвовать как внутренние, так и внешние переменные запроса (если существуют внутренняя и внешняя переменные с одинаковым именем, то использоваться по данному имени будет внутренняя переменная).

Пример:

Условие(Цена > 23.5);
Условие((Товар.ПринадлежитГруппе(ВыбТовар) = 1) И (Товар.Розн_Цена = 100));

Использование двух операторов

Условие(Товар.Наименование <> "Стол");
Условие(Товар.Наименование <> "Шкаф");

аналогично одному оператору

Условие((Товар.Наименование <> "Стол") И (Товар.Наименование <> "Шкаф"));

Кроме обычных логических операторов в операторе Условие() языка запросов можно использовать дополнительный оператор — логический оператор принадлежности В (англоязычный синоним — In). Тогда, например, оператор языка запросов Условие (А в Б); будет говорить о том, что условие истинно, когда значение А является подмножеством значения Б. Причём, следует особо отметить, что если значение Б будет пустое (объект не выбран), то условие будет является истинным, в отличии от оператора = (равно).

Если на принадлежность проверяется значение типа "элемент справочника", то проверка выполняется с учётом его возможного вхождения в группу справочника. Аналогично, проверка на принадлежность субсчёта осуществляется с учётом его возможного вхождения в группу счетов.

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

Оператор принадлежности существенно облегчает написание текстов запроса, делает их более понятными. Рассмотрим пример запроса без использования логического оператора принадлежности:

Текст3апроса = "
 . . .
|Товар = Документ.ВидДокумента.Товар;";
 . . .
|"
;

Если ВыбТовар.Выбран() = 1 Тогда
   Если ВыбТовар.ЭтоГруппа() = 1 Тогда
      ТекстЗапроса = ТекстЗапроса + "Условие(Товар.ПринадлежитГруппе(ВыбТовар) = 1);";
   Иначе
      ТекстЗапроса = ТекстЗапроса + "Условие(Товар = ВыбТовар);";
   КонецЕсли
КонецЕсли;

А теперь тот же пример, но с использованием логического оператора принадлежности:

Текст3апроса = "
 . . .
|Товар = Документ.ВидДокумента.Товар;";
 . . .
|Условие(Товар В ВыбТовар);
 . . .
|"
;

Примеры использования запросов

Печать каталога товаров

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

Процедура ПечатьСправочника()
   
   Перем Запрос, ТекстЗапроса, Таб;
   
   Запрос = СоздатьОбъект("Запрос");
   Текст3апроса = "//{{ЗАПРОС(Печать)
   |Товар = Справочник.Товары.ТекущийЭлемент;
   |Группировка Товар Упорядочить по Товар.МинЗапас;
   |"
   ;
   
   Если Запрос.Выполнить(ТекстЗапроса) = 0 Тогда
      Возврат;
   КонецЕсли;
   
   Таб = СоздатьОбъект("Таблица");
   Таб.ВывестиСекцию("Отчет");
   Пока Запрос.Группировка("Товар") = 1 Цикл
      
      Если Запрос.Товар.ЭтоГруппа() = 1 Тогда
         Таб.ВывестиСекцию("Группа");
      Иначе
         Таб.ВывестиСекцию("Товар");
      КонецЕсли;
   КонецЦикла;
   
   Таб.Опции(0, 0, 4, 0);
   Таб.ТолькоПросмотр(1);
   Таб.Показать("Список товаров по каталогу", "");
КонецПроцедуры

Отчёт по неходовым товарам

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

Процедура Сформировать()
   Перем Запрос, ТекстЗапроса, Таб;
   Рег = СоздатьОбъект("Регистр.ОстаткиТовара");
   Запрос = СоздатьОбъект("Запрос");
   ТекстЗапроса = "//{{ЗАПРОС(Сформировать)
   |Период С ДатаНачала По ДатаКонца;
   |ТОВАР = Документ.РасходнаяБН.Товар, 
   |   Документ.РасходнаяКредит.Товар, Документ.РасходнаяНал.Товар,
   |   Документ.РасходнаяРеализ.Товар, Документ.Счет.Товар;
   |Группировка ТОВАР упорядочить по ТОВАР.Наименование без групп;
   |"
   ;
   Если ДатаКонца >= ПолучитьДатуТА() Тогда
      ТекстЗапроса = ТекстЗапроса + "Период С ДатаНачала;";
   Иначе
      ТекстЗапроса = ТекстЗапроса + "Период С ДатаНачала По ДатаКонца;";
      Peг.ВременныйРасчет();
      РассчитатьРегистрыНа(ДатаКонца);
   КонецЕсли;
   
   Если Запрос.Выполнить(ТекстЗапроса) = 0 Тогда
      Возврат;
   КонецЕсли;
   Тов = СоздатьОбъект("Справочник.Товары");
   
   Тов.ВключатьПодчиненные(1);
   
   Тов.ПорядокНаименований();
   ИтогоОстаток = 0;
   ИтогоСумма = 0;
   Таб = СоздатьОбъект("Таблица");
   Таб.ВывестиСекцию("Отчет");
   
   Тов.ВыбратьЭлементы();
   Пока Тов.ПолучитьЭлемент() > 0 Цикл
      Флаг = 0;
      Товар = Тов.ТекущийЭлемент();
      Если Товар.ЭтоГруппа() = 1 Тогда
         Продолжить;
      КонецЕсли;
      
      Если Запрос.Получить(Товар) = 1 Тогда
         Продолжить;
      КонецЕсли;
      
      Рег.СводныеОстатки(Товар, );
      ТекОстаток = Рег.ОстатокТовара;
      ТекСумма = Рег.БазоваяСтоимость;
      Если ТекОстаток = 0 Тогда
         Продолжить;
      КонецЕсли;
      Таб.ВывестиСекцию("Товар");
      ИтогоОстаток = ИтогоОстаток + ТекОстаток;
      ИтогоСумма = ИтогоСумма + ТекСумма;
   КонецЦикла;
   Таб.ВывестиСекцию("Итоги");
   Таб.ТолькоПросмотр(1);
   Таб.Опции(0, 0, 3, 0);
   Таб.Показать("Отчет о неходовых товарах", "");
КонецПроцедуры



ДатаКонца = РабочаяДата();
ДатаНачала = ДатаКонца — Константа.ПериодАнализа;

Отчёт по регистру с точностью до строки документа

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

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

Процедура Сформировать()
   Перем Запрос, ТекстЗапроса, Таб;
   
   Запрос = СоздатьОбъект("Запрос");
   ТекстЗапроса = "//{{ЗАПРОС(Сформировать)
   |Период с НачДата по КонДата;
   |ВидТоплива = Регистр.ПокупателиКолво.ВидыТоплива;
   |Вес = Регистр.ПокупателиКолво.Кг;
   |Покуп = Регистр.ПокупателиКолво.Покупатели;
   |Док = Регистр.ПокупателиКолво.ТекущийДокумент;
   |Ном = Регистр.ПокупателиКолво.НомерСтроки;
   |Группировка ВидТоплива;      // по измерению Регистра
   |Группировка Док;             // по документам, двигавшим Регистр
   |Группировка Ном;             // по номерам строк документов
   |Функция ВсегоКолво = КонОст(Вес);
   |Функция ПриходКолво = Приход(Вес);
   |Условие(Покуп = ВыбПокупатель);
   |"
   ;
   
   Если Запрос.Выполнить(ТекстЗапроса) = 0 Тогда
      Возврат;
   КонецЕсли;
   
   Таб = СоздатьОбъект("Таблица");
   Таб.ИсходнаяТаблица("Таблица1");
   Таб.ВывестиСекцию("Шапка");
   Пока Запрос.Группировка(1) = 1 Цикл
      
      Таб.ВывестиСекцию("ВидТоплива");
      
      Пока Запрос.Группировка(2) = 1 Цикл
         Док1 = Запрос.Док;
         
         Если НЕ(Док1.Вид() = "Продажа") Тогда
            Продолжить;
         КонецЕсли;
         
         Пока Запрос.Группировка(3) = 1 Цикл
            
            Док1.ПолучитьСтрокуПоНомеру(Запрос.Ном);
            Таб.ВывестиСекцию("Строка");
         КонецЦикла;
      КонецЦикла;
   КонецЦикла;
   
   Таб.Опции(0, 0, 0, 0);
   Таб.ТолькоПросмотр(1);
   Таб.Показать("", "");
КонецПроцедуры

Анализ счёта

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

Процедура АнализСчета()
   Перем Запрос, ТекстЗапроса, Таб;
   
   Запрос = СоздатьОбъект("Запрос");
   ТекстЗапроса = "//{{ЗАПРОС(Сформировать)
   |Период с ДатаС по ДатаПо;
   |Сч = Операция.Счет;
   |КорСч = Операция.КорСчет;
   |Сумма = Операция.Сумма;
   |Группировка Сч упорядочить по Сч.Код;
   |Группировка КорСч упорядочить по КорСч.Код;
   |Функция КорДо = КорДО(Сумма);
   |Функция КорКо = КорКО(Сумма);
   |Условие(Сч = ВыбСч);
   |"
   ;
   
   Если Запрос.Выполнить(ТекстЗапроса) = 0 Тогда
      Возврат;
   КонецЕсли;
   
   Таб = СоздатьОбъект("Таблица");
   Таб.ИсходнаяТаблица("Сформировать");
   
   Таб.ВывестиСекцию("Заголовок");
   Состояние("Заполнение выходной таблицы...");
   Пока Запрос.Группировка("Сч") = 1 Цикл
      
      Таб.ВывестиСекцию("Сч");
      Пока Запрос.Группировка("КорСч") = 1 Цикл
         
         Таб.ВывестиСекцию("КорСч");
      КонецЦикла;
   КонецЦикла;
   
   Таб.ВывестиСекцию("Итого");
   
   Таб.Опции(1, 0, 1, 0);
   Таб.Показать("Сформировать", "");
КонецПроцедуры

Разработка вложенных отчётов

Средства программы «1С:Предприятие» по работе с таблицами позволяют создавать эффектные отчёты, причём на экране монитора отображается не просто мёртвая картинка предварительного просмотра печати, а живой отчёт, который можно редактировать или непосредственно из него вызывать дополнительную поясняющую информацию.

Поскольку каждая ячейка таблицы может содержать значение, записанное в неё, то в программном модуле формы отчёта возможно обрабатывать это значение. Обработка значения ячейки таблицы вызывается системой по клавише Enter или по двойному щелчку мышью на какой-либо ячейке (если режим «только просмотр»). Стандартными действиями системы на обработку такого события являются: для документа — открытие документа, для элемента справочника — открытие формы редактирования элемента справочника. Другими словами, стандартные действия системы зависят от типа данных содержащегося в ячейке значения. Однако, это событие возможно перехватить и обработать нестандартным способом. Для этого предназначена предопределённая процедура встроенного языка ОбработкаЯчейкиТаблицы().

Примером нестандартной обработки значения ячейки таблицы может быть, например, вызов на формирование другого отчёта. Таким образом, мы можем создавать как бы вложенные отчёты, которые вызываются один из другого, выдавая с каждым разом более детальную информацию. Допустим отчёт «Взаиморасчеты» при формировании всегда выводится в кратком виде, когда виден только сводный баланс по контрагенту. Для того, чтобы получить детальный отчёт по данному контрагенту, достаточно встать курсором в готовой форме отчёта на этого контрагента и нажать клавишу Enter. Тогда сработает процедура ОбработкаЯчейкиТаблицы(), в которой можно записать вызов формирования детального отчёта. А если, кроме того, завести флаг режима отображения, то можно вместо этого показывать карточку этого контрагента из справочника.

Рассмотрим построение вложенных отчётов на примере. Допустим, у вас есть отчёт «ПродажиТоваров», в котором отображается перечень товаров, количество и сумма проданных за некоторый период товаров. Программный модуль формирования такого отчёта приведён ниже.

Процедура ПродВсего()
   Перем Запрос, ТекстЗапроса, Таб;
   ДатаКон = ДатаКонца;
   Если ДатаКон >= ПолучитьДатуТА() Тогда
      ДатаКон = Дата(0);
   КонецЕсли;
   
   Запрос = СоздатьОбъект("Запрос");
   ТекстЗапроса = "//{{ЗАПРОС(ПродВсего)
   |Период с ДатаНачала по ДатаКон;
   |ТОВАР = Документ.РасхНакл.Товар;
   |Сумма_Прод = Документ.РасхНакл.СуммаРуб;
   |КОЛВО_Прод = Документ.РасхНакл.Количество;
   |Группировка ТОВАР;
   |Функция Продано = Сумма(КОЛВО_Прод);
   |Функция СуммаПродано = Сумма(Сумма_Прод);
   |"
   ;
   
   Если Запрос.Выполнить(ТекстЗапроса) = 0 Тогда
      Возврат;
   КонецЕсли;
   
   Таб = СоздатьОбъект("Таблица");
   Таб.ИсходнаяТаблица("ТабВсего");
   Таб.ВывестиСекцию("Отчет");
   Пока Запрос.Группировка("Товар") = 1 Цикл
      ПродСумма = Запрос.СуммаПродано;
      Если Запрос.Товар.ЭтоГруппа() = 1 Тогда
         Таб.ВывестиСекцию("Группа");
      Иначе
         Таб.ВывестиСекцию("Товар");
      КонецЕсли;
   КонецЦикла;
   
   Таб.ТолькоПросмотр(1);
   Таб.Опции(0, 0, 4, 0);
   Таб.Показать("Продажа товаров", "");
КонецПроцедуры

В режиме исполнения у нас получится такой отчёт:

Отчёт

Далее, допустим, мы хотим получить более подробный отчёт по конкретному товару, так, чтобы указав на товар в отчёте, и дважды нажав кнопку мыши, мы получали отчёт по продажам именно этого товара с точностью до каждого клиента. Для этого откроем в Конфигураторе редактор таблицы нашего отчёта и в свойствах ячейки (Свойства ячейки -> Текст -> поле «Значение»), отображающей наименование товара, проставим значение ячейки — «Запрос.Товар».

Далее, в программном модуле напишем процедуру формирования дополнительного отчёта:

Процедура ПродТовар(ВТовар)
   Перем Запрос, ТекстЗапроса, Таб;
   ДатаКон = ДатаКонца;
   Если ДатаКон >= ПолучитьДатуТА() Тогда
      ДатаКон = Дата(0);
   КонецЕсли;
   
   Запрос = СоздатьОбъект("Запрос");
   ТекстЗапроса = "//{{ЗАПРОС(ПродТовар)
   |Период с ДатаНачала по ДатаКон;
   |КЛИЕНТ = Документ.РасхНакл.Клиент;
   |ТОВАР = Документ.РасхНакл.Товар;
   |СУММ = Документ.РасхНакл.СуммаВал;
   |КОЛВО = Документ.РасхНакл.Количество;
   |Группировка КЛИЕНТ Упорядочить По КЛИЕНТ.Наименование;
   |Группировка ТОВАР Упорядочить По ТОВАР.Наименование;
   |Функция Продано = Сумма(КОЛВО);
   |Функция ПродСум = Сумма(СУММ);
   |"
   ;
   Если ВТовар.Выбран() = 1 Тогда
      Если ВТовар.ЭтоГруппа() = 1 Тогда
         ТекстЗапроса = ТекстЗапроса + "Условие(Товар.ПринадлежитГруппе(ВТовар) = 1);";
      Иначе
         ТекстЗапроса = ТекстЗапроса + "Условие (Товар = ВТовар);";
         ФОдинТовар = 1;
      КонецЕсли;
   КонецЕсли;
   
   Если Запрос.Выполнить(ТекстЗапроса) = 0 Тогда
      Возврат;
   КонецЕсли;
   
   Таб = СоздатьОбъект("Таблица");
   Таб.ВывестиСекцию("Отчет");
   Пока Запрос.Группировка("Клиент") = 1 Цикл
      Таб.ВывестиСекцию("Клиент");
      Пока Запрос.Группировка("Товар") = 1 Цикл
         Если ФОдинТовар = 0 Тогда
            Таб.ВывестиСекцию("Товар");
         КонецЕсли;
      КонецЦикла;
   КонецЦикла;
   
   Таб.ТолькоПросмотр(1);
   Таб.Опции(0, 4, 0, 0);
   Таб.Показать("Продажа товара", "");
КонецПроцедуры

Теперь нам осталось написать предопределённую процедуру, которая возьмёт на себя обработку события «двойной щелчок мышью на выбранной ячейке таблицы». Главная задача этой процедуры — определить, что выбрана ячейка, где указано значение товара и вызвать на исполнение процедуру формирования дополнительного отчёта, написанную ранее.

Процедура ОбработкаЯчейкиТаблицы(ЗначЯч, ФлагСтандартнойОбработки)   
   Если ТипЗначения(ЗначЯч) = 2 Тогда
      ФлагСтандартнойОбработки = 1;
      Возврат;
   КонецЕсли;
   ПродТовар(ЗначЯч);
КонецПроцедуры

Теперь, в режиме исполнения, если в отчёте «Продажи товаров» мы укажем курсором на товар, например, «Сапоги женские» и дважды щёлкнем на нём мышью, то сформируется дополнительный подробный отчёт «Продажа товара».

Способы оптимизации формирования отчётов

Процесс получения отчётов с использованием запросов можно условно разделить на две фазы: сначала формируется запрос, затем полученные данные выводятся в таблицу. В данном разделе речь пойдёт о второй фазе получения отчёта — выводе данных в таблицу.

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

Вариант 1:

В программном модуле текст вывода данных в таблицу следующий:

Пока Запрос.Группировка("Товар") = 1 Цикл
   Таб.ВывестиСекцию("Товар");
КонецЦикла;

Секция "Товар" в таблице имеет следующий формат:

Секция'Товар'

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

Вариант 2:

В программном модуле текст вывода данных в таблицу следующий:

Пока Запрос.Группировка("Товар") = 1 Цикл
   ПечНаим = Запрос.Товар.Наименование;
   ПечАртикул = Запрос.Товар.Артикул;
   ПечЦена = Запрос.Товар.Цена;
   ПечВалюта = Запрос.Товар.Валюта;
   Таб.ВывестиСекцию("Товар1");
КонецЦикла;

Секция "Товар1" в таблице имеет следующий формат:

Секция'Товар1'

Во этом варианте отображаемые реквизиты товара вычисляются в программном модуле, а в ячейках таблицы размещены простые выражения — ссылки на идентификаторы программного модуля. Доступ к каждому реквизиту товара, как и в первом варианте, происходит по полному пути: Запрос-Товар-Реквизит. Но в данном варианте фаза вывода данных в таблицу работает быстрее первого варианта (выигрыш примерно 20%), так как в программном модуле выражения вычисляются существенно быстрее, чем выражения, помещённые в ячейках таблицы (программный модуль при загрузке компилируется, а выражения в ячейках таблицы интерпретируются каждый раз при выводе секций).

Вариант 3:

В программном модуле текст вывода данных в таблицу следующий:

Пока Запрос.Группировка("Товар") = 1 Цикл
   Тов = Запрос.Товар;
   ПечНаим = Тов.Наименование;
   ПечАртикул = Тов.Артикул;
   ПечЦена = Тов.Цена;
   ПечВалюта = Тов.Валюта;
   Таб.ВывестиСекцию("Товар1");
КонецЦикла;

Секция «Товар1» в таблице имеет следующий формат:

Секция'Товар1'

В этом варианте отображаемые реквизиты товара также вычисляются в программном модуле, а в ячейках таблицы размещены простые выражения — ссылки на идентификаторы программного модуля. Однако доступ к каждому реквизиту товара происходит по сокращённому пути — через промежуточную переменную: Товар—Реквизит. Поэтому в данном варианте фаза вывода данных в таблицу работает быстрее, чем во втором варианте (выигрыш примерно 20%) и существенно быстрее, чем в первом варианте (выигрыш примерно 40%), так как вычисление значений реквизитов объектов через «одну точку» выполняется быстрее, чем через «две (и более) точки».

Отсюда вывод: при реализации больших отчётов, которые рассчитаны на отображение более сотни строк:

  • не следует размещать сложные выражения в ячейках таблицы. Лучше вычислить необходимые значения непосредственно в программном модуле;
  • если необходимо получить несколько реквизитов одного объекта, который сам является составной частью другого объекта, то следует воспользоваться промежуточной переменной, в которую сначала можно записать значение всего объекта «целиком», а затем уже от неё получать требуемые данные.

Другие статьи по схожей тематике

  • Работы с табличными формами
  • Работа со справочниками в 1С
  • Работа с объектами типа "Документ"
  • Работа с типом данных "Счет"
  • Работа с операциями и проводками
  • Работа с бухгалтерскими итогами
  • Работа с регистрами оперативного учёта

Показывать по
10
20
40
сообщений

Новая тема

Ответить

Ivan_Ivanov

Дата регистрации: 06.06.2007
Сообщений: 168

«Текст запроса:<br> Запрос.Текст = <br> «ВЫБРАТЬ<br> | СведенияОДоходах.ФизЛицо,<br> | МЕСЯЦ(СведенияОДоходах.Период) КАК Месяц,<br> | СведенияОДоходах.ОблагаетсяЕНВД,<br> | СведенияОДоходах.ОблагаетсяПоДополнительномуТарифу,<br> | СведенияОДоходах.ВидДохода,<br> | СведенияОДоходах.Результат — СведенияОДоходах.Скидка КАК ОблагаемыйДоход<br> |ПОМЕСТИТЬ ВТДанныеДокумента<br> |ИЗ<br> | &ДанныеОДоходах КАК СведенияОДоходах»;<br> Запрос.УстановитьПараметр(«ДанныеОДоходах», ДанныеОДоходах);<br> Запрос.Выполнить();<br> <br> // ФизлицаДляРасчета<br> //<br> Если ОрганичениеНаСотрудников = Неопределено Тогда<br> <br> Запрос.Текст = <br> «ВЫБРАТЬ РАЗЛИЧНЫЕ<br> | СведенияОДоходах.ФизЛицо КАК ФизЛицо<br> |ПОМЕСТИТЬ ВТСписокСотрудников<br> |ИЗ<br> | РегистрНакопления.СтраховыеВзносыСведенияОДоходах КАК СведенияОДоходах<br> |ГДЕ<br> | НАЧАЛОПЕРИОДА(СведенияОДоходах.Период, МЕСЯЦ) = &парамПериодРегистрации<br> | И СведенияОДоходах.ОбособленноеПодразделение = &парамОбособленноеПодразделение<br> |<br> |ОБЪЕДИНИТЬ<br> |<br> |ВЫБРАТЬ РАЗЛИЧНЫЕ<br> | СведенияОДоходах.ФизЛицо<br> |ИЗ<br> | ВТДанныеДокумента КАК СведенияОДоходах<br> |<br> |ИНДЕКСИРОВАТЬ ПО<br> | ФизЛицо»;<br> Запрос.Выполнить();<br> <br> Иначе<br> Запрос.Текст = <br> «ВЫБРАТЬ РАЗЛИЧНЫЕ<br>       | ТаблицаСотрудников.ФизЛицо КАК ФизЛицо<br>       |ПОМЕСТИТЬ ВТСписокСотрудников<br>       |ИЗ<br>       | &парамТаблицаСотрудников КАК ТаблицаСотрудников<br>       |<br>       |ИНДЕКСИРОВАТЬ ПО<br>       | ФизЛицо»;<br> Запрос.УстановитьПараметр(«парамТаблицаСотрудников», ОрганичениеНаСотрудников);<br> Запрос.Выполнить();<br> КонецЕсли;<br> <br> // Периоды<br> // Таблица список периодов<br> // Поля:<br> // Период<br> // Описание:<br> // список периодов — первые даты месяцев с начала года по «текущий» для запроса период<br> //<br> <br> // конец месяца налогового периода<br> КонецМесяца = КонецМесяца(НачалоГода(ПериодРегистрации));<br> // первый месяц<br> ПериодыТекст = «ВЫБРАТЬ ДАТАВРЕМЯ(» + Формат(КонецМесяца,»ДФ=гггг,М,д,Ч,м,с») + «) КАК Период ПОМЕСТИТЬ ВТПериоды»;<br> // прибавим остальные месяцы<br> Для Сч = 2 По Месяц(ПериодРегистрации) Цикл<br> КонецМесяца = КонецМесяца(КонецМесяца+1);<br> ПериодыТекст = ПериодыТекст +» ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ ДАТАВРЕМЯ(» + Формат(КонецМесяца,»ДФ=гггг,М,д,Ч,м,с») + «)»;<br> КонецЦикла;<br> Запрос.Текст = ПериодыТекст;<br> Запрос.Выполнить();<br><br> Запрос.Текст = <br> «ВЫБРАТЬ<br> | МЕСЯЦ(Периоды.Период) КАК Месяц,<br> | ЕСТЬNULL(УчетнаяПолитикаНалоговыйУчет.ВидТарифаСтраховыхВзносов, ЗНАЧЕНИЕ(Перечисление.ТарифыСтраховыхВзносов.ОбщийНалоговыйРежим)) КАК ВидТарифаСтраховыхВзносов<br> |ПОМЕСТИТЬ ВТИспользуемыеТарифы<br> |ИЗ<br> | (ВЫБРАТЬ<br> | Периоды.Период КАК Период,<br> | МАКСИМУМ(УчетнаяПолитикаНалоговыйУчет.Период) КАК ПериодРегистра<br> | ИЗ<br> | ВТПериоды КАК Периоды<br> | ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.УчетнаяПолитикаНалоговыйУчет КАК УчетнаяПолитикаНалоговыйУчет<br> | ПО Периоды.Период >= УчетнаяПолитикаНалоговыйУчет.Период<br> | И (УчетнаяПолитикаНалоговыйУчет.Организация = &парамГоловнаяОрганизация)<br> | <br> | СГРУППИРОВАТЬ ПО<br> | Периоды.Период) КАК Периоды<br> | ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.УчетнаяПолитикаНалоговыйУчет КАК УчетнаяПолитикаНалоговыйУчет<br> | ПО Периоды.ПериодРегистра = УчетнаяПолитикаНалоговыйУчет.Период<br> | И (УчетнаяПолитикаНалоговыйУчет.Организация = &парамГоловнаяОрганизация)<br> |<br> |ИНДЕКСИРОВАТЬ ПО<br> | Месяц<br> |;<br> |<br> |////////////////////////////////////////////////////////////­////////////////////<br> |ВЫБРАТЬ<br> | ТарифСтраховыхВзносовСрезПоследних.ВидТарифа КАК ВидТарифа,<br> | ТарифСтраховыхВзносовСрезПоследних.ПФР,<br> | ТарифСтраховыхВзносовСрезПоследних.ПФРНакопительная,<br> | ТарифСтраховыхВзносовСрезПоследних.ФСС,<br> | ТарифСтраховыхВзносовСрезПоследних.ФФОМС,<br> | ТарифСтраховыхВзносовСрезПоследних.ТФОМС<br> |ПОМЕСТИТЬ ВТТарифы<br> |ИЗ<br> | РегистрСведений.ТарифСтраховыхВзносов.СрезПоследних(&парамКонецГода, ) КАК ТарифСтраховыхВзносовСрезПоследних<br> |<br> |ИНДЕКСИРОВАТЬ ПО<br> | ВидТарифа<br> |;<br> |<br> |////////////////////////////////////////////////////////////­////////////////////<br> |ВЫБРАТЬ<br> | МЕСЯЦ(Периоды.Период) КАК Месяц,<br> | ГражданствоФизЛиц.ФизЛицо КАК Физлицо,<br> | ЕСТЬNULL(ГражданствоФизЛиц.НеИмеетПравоНаПенсию, ЛОЖЬ) КАК НеИмеетПравоНаПенсию,<br> | ЕСТЬNULL(ГражданствоФизЛиц.НеИмеетПравоНаМедицинскоеСтрахование, ЛОЖЬ) КАК НеИмеетПравоНаМедицинскоеСтрахование<br> |ПОМЕСТИТЬ ВТДанныеОПравеНаПенсию<br> |ИЗ<br> | (ВЫБРАТЬ<br> | Периоды.Период КАК Период,<br> | ГражданствоФизЛиц.ФизЛицо КАК Физлицо,<br> | МАКСИМУМ(ГражданствоФизЛиц.Период) КАК ПериодРегистра<br> | ИЗ<br> | ВТПериоды КАК Периоды<br> | ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.ГражданствоФизЛиц КАК ГражданствоФизЛиц<br> | ПО Периоды.Период >= ГражданствоФизЛиц.Период<br> | ГДЕ<br> | ГражданствоФизЛиц.ФизЛицо В<br> | (ВЫБРАТЬ<br> | СписокСотрудников.ФизЛицо<br> | ИЗ<br> | ВТСписокСотрудников КАК СписокСотрудников)<br> | <br> | СГРУППИРОВАТЬ ПО<br> | ГражданствоФизЛиц.ФизЛицо,<br> | Периоды.Период) КАК Периоды<br> | ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.ГражданствоФизЛиц КАК ГражданствоФизЛиц<br> | ПО Периоды.ПериодРегистра = ГражданствоФизЛиц.Период<br> | И Периоды.Физлицо = ГражданствоФизЛиц.ФизЛицо<br> | И (ГражданствоФизЛиц.НеИмеетПравоНаПенсию<br> | ИЛИ ГражданствоФизЛиц.НеИмеетПравоНаМедицинскоеСтрахование)<br> |<br> |ИНДЕКСИРОВАТЬ ПО<br> | Физлицо,<br> | Месяц<br> |;<br> |<br> |////////////////////////////////////////////////////////////­////////////////////<br> |ВЫБРАТЬ<br> | СведенияОбИнвалидностиФизлиц.Физлицо КАК Физлицо,<br> | СведенияОбИнвалидностиФизлиц.Период КАК Период,<br> | СведенияОбИнвалидностиФизлиц.Инвалидность<br> |ПОМЕСТИТЬ ВТ_СведенияОбИнвалидности<br> |ИЗ<br> | РегистрСведений.СведенияОбИнвалидностиФизлиц КАК СведенияОбИнвалидностиФизлиц<br> |ГДЕ<br> | СведенияОбИнвалидностиФизлиц.Физлицо В<br> | (ВЫБРАТЬ<br> | СписокСотрудников.ФизЛицо<br> | ИЗ<br> | ВТСписокСотрудников КАК СписокСотрудников)<br> |<br> |ИНДЕКСИРОВАТЬ ПО<br> | Физлицо,<br> | Период<br> |;<br> |<br> |////////////////////////////////////////////////////////////­////////////////////<br> |ВЫБРАТЬ<br> | МЕСЯЦ(Периоды.Период) КАК Месяц,<br> | СведенияОбИнвалидностиФизлиц.Физлицо КАК Физлицо<br> |ПОМЕСТИТЬ ВТДанныеОбИнвалидности<br> |ИЗ<br> | (ВЫБРАТЬ<br> | Периоды.Период КАК Период,<br> | СведенияОбИнвалидностиФизлиц.Физлицо КАК Физлицо,<br> | МАКСИМУМ(СведенияОбИнвалидностиФизлиц.Период) КАК ПериодРегистра<br> | ИЗ<br> | ВТПериоды КАК Периоды<br> | ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_СведенияОбИнвалидности КАК СведенияОбИнвалидностиФизлиц<br> | ПО Периоды.Период >= СведенияОбИнвалидностиФизлиц.Период<br> | <br> | СГРУППИРОВАТЬ ПО<br> | СведенияОбИнвалидностиФизлиц.Физлицо,<br> | Периоды.Период) КАК Периоды<br> | ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_СведенияОбИнвалидности КАК СведенияОбИнвалидностиФизлиц<br> | ПО (СведенияОбИнвалидностиФизлиц.Период = Периоды.ПериодРегистра)<br> | И Периоды.Физлицо = СведенияОбИнвалидностиФизлиц.Физлицо<br> | И (СведенияОбИнвалидностиФизлиц.Инвалидность)<br> |<br> |ИНДЕКСИРОВАТЬ ПО<br> | Физлицо,<br> | Месяц<br> |;<br> |<br> |////////////////////////////////////////////////////////////­////////////////////<br> |ВЫБРАТЬ<br> | СведенияОДоходах.ФизЛицо КАК ФизЛицо,<br> | МЕСЯЦ(СведенияОДоходах.Период) КАК Месяц,<br> | СведенияОДоходах.ОблагаетсяЕНВД,<br> | СведенияОДоходах.ОблагаетсяПоДополнительномуТарифу,<br> | СведенияОДоходах.ВидДохода.ВходитВБазуПФР КАК ВходитВБазуПФР,<br> | СведенияОДоходах.ВидДохода.ВходитВБазуФСС КАК ВходитВБазуФСС,<br> | СведенияОДоходах.ВидДохода.ВходитВБазуФОМС КАК ВходитВБазуФОМС,<br> //мов++<br> | СведенияОДоходах.ВидДохода.ВходитВПАВ КАК ВходитВПАВ,<br> | СведенияОДоходах.ВидДохода.Внебюджет КАК Внебюджет,<br> | СведенияОДоходах.ВидДохода.ВходитВДГПХ КАК ВходитВДГПХ,<br> | СведенияОДоходах.РезультатОборот — СведенияОДоходах.СкидкаОборот КАК ОблагаемыйДоход<br> //| СведенияОДоходах.РезультатОборотПАВ — СведенияОДоходах.СкидкаОборот КАК ОблагаемыйДоходПАВ<br> |ПОМЕСТИТЬ ВТДоходыПоФизлицамМесяцам<br> |ИЗ<br> | РегистрНакопления.СтраховыеВзносыСведенияОДоходах.Обороты(<br> | &парамНачалоГода,<br> | &парамКонецМесяцаПериодаРегистрации,<br> | Месяц,<br> | Организация = &парамГоловнаяОрганизация<br> | И Физлицо В<br> | (ВЫБРАТЬ<br> | СписокСотрудников.ФизЛицо<br> | ИЗ<br> | ВТСписокСотрудников КАК СписокСотрудников)) КАК СведенияОДоходах<br> |<br> |ОБЪЕДИНИТЬ ВСЕ<br> |<br> |ВЫБРАТЬ<br> | СтраховыеВзносыСведенияОДоходах.ФизЛицо,<br> | МЕСЯЦ(СтраховыеВзносыСведенияОДоходах.Период),<br> | СтраховыеВзносыСведенияОДоходах.ОблагаетсяЕНВД,<br> | СтраховыеВзносыСведенияОДоходах.ОблагаетсяПоДополнительномуТарифу,<br> | СтраховыеВзносыСведенияОДоходах.ВидДохода.ВходитВБазуПФР,<br> | СтраховыеВзносыСведенияОДоходах.ВидДохода.ВходитВБазуФСС,<br> | СтраховыеВзносыСведенияОДоходах.ВидДохода.ВходитВБазуФОМС,<br> //мов++<br> | СтраховыеВзносыСведенияОДоходах.ВидДохода.ВходитВПАВ,<br> | СтраховыеВзносыСведенияОДоходах.ВидДохода.ВходитВДГПХ,<br> | СтраховыеВзносыСведенияОДоходах.ВидДохода.Внебюджет,<br><br><br><br> | -СтраховыеВзносыСведенияОДоходах.Результат + СтраховыеВзносыСведенияОДоходах.Скидка<br> |ИЗ<br> | РегистрНакопления.СтраховыеВзносыСведенияОДоходах КАК СтраховыеВзносыСведенияОДоходах<br> |ГДЕ<br> | СтраховыеВзносыСведенияОДоходах.Регистратор = &Регистратор<br> | И СтраховыеВзносыСведенияОДоходах.Организация = &парамГоловнаяОрганизация<br> | И СтраховыеВзносыСведенияОДоходах.ФизЛицо В<br> | (ВЫБРАТЬ<br> | СписокСотрудников.ФизЛицо<br> | ИЗ<br> | ВТСписокСотрудников КАК СписокСотрудников)<br> |<br> |ОБЪЕДИНИТЬ ВСЕ<br> |<br> |ВЫБРАТЬ<br> | СтраховыеВзносыСведенияОДоходах.ФизЛицо,<br> | СтраховыеВзносыСведенияОДоходах.Месяц,<br> | СтраховыеВзносыСведенияОДоходах.ОблагаетсяЕНВД,<br> | СтраховыеВзносыСведенияОДоходах.ОблагаетсяПоДополнительномуТарифу,<br> | СтраховыеВзносыСведенияОДоходах.ВидДохода.ВходитВБазуПФР,<br> | СтраховыеВзносыСведенияОДоходах.ВидДохода.ВходитВБазуФСС,<br> | СтраховыеВзносыСведенияОДоходах.ВидДохода.ВходитВБазуФОМС,<br> //мов++<br> | СтраховыеВзносыСведенияОДоходах.ВидДохода.ВходитВПАВ,<br> | СтраховыеВзносыСведенияОДоходах.ВидДохода.ВходитВДГПХ,<br> | СтраховыеВзносыСведенияОДоходах.ВидДохода.Внебюджет,<br><br><br> //| СтраховыеВзносыСведенияОДоходах.ОблагаемыйДоходПАВ,<br><br> | СтраховыеВзносыСведенияОДоходах.ОблагаемыйДоход<br> |ИЗ<br> | ВТДанныеДокумента КАК СтраховыеВзносыСведенияОДоходах<br> |<br> |ИНДЕКСИРОВАТЬ ПО<br> | ФизЛицо,<br> | Месяц<br> |;<br> |<br> |////////////////////////////////////////////////////////////­////////////////////<br> |ВЫБРАТЬ<br> | СведенияОДоходах.ФизЛицо КАК ФизЛицо<br> |ПОМЕСТИТЬ ВТФизлицаБезОблагаемойБазы<br> |ИЗ<br> | ВТДоходыПоФизлицамМесяцам КАК СведенияОДоходах<br> |<br> |СГРУППИРОВАТЬ ПО<br> | СведенияОДоходах.ФизЛицо<br> |<br> |ИМЕЮЩИЕ<br> | СУММА(ВЫБОР<br> | КОГДА СведенияОДоходах.ВходитВБазуПФР<br> //мов<br> | ИЛИ СведенияОДоходах.ВходитВБазуФОМС ИЛИ СведенияОДоходах.ВходитВПАВ ИЛИ СведенияОДоходах.ВходитВДГПХ ИЛИ СведенияОДоходах.Внебюжет<br> | ТОГДА СведенияОДоходах.ОблагаемыйДоход<br> | ИНАЧЕ 0<br> | КОНЕЦ) < 0<br> |<br> |ИНДЕКСИРОВАТЬ ПО<br> | ФизЛицо<br> |;<br> |<br> |////////////////////////////////////////////////////////////­////////////////////<br> |ВЫБРАТЬ<br> | РанееИсчисленныеВзносы.ФизЛицо КАК ФизЛицо,<br> | МЕСЯЦ(РанееИсчисленныеВзносы.Период) КАК Месяц,<br> | РанееИсчисленныеВзносы.ФССОборот,<br> | РанееИсчисленныеВзносы.ФФОМСОборот,<br> | РанееИсчисленныеВзносы.ТФОМСОборот,<br> | РанееИсчисленныеВзносы.ПФРНакопительнаяОборот,<br> | РанееИсчисленныеВзносы.ПФРСтраховаяОборот,<br> | РанееИсчисленныеВзносы.ПФРНакопительнаяЕНВДОборот,<br> | РанееИсчисленныеВзносы.ПФРСтраховаяЕНВДОборот,<br> | РанееИсчисленныеВзносы.ПФРПоДополнительномуТарифуОборот,<br> //мов++<br> | РанееИсчисленныеВзносы.ФССПАВОборот,<br> | РанееИсчисленныеВзносы.ФФОМСПАВОборот,<br> | РанееИсчисленныеВзносы.ТФОМСПАВОборот,<br> | РанееИсчисленныеВзносы.ПФРНакопительнаяПАВОборот,<br> | РанееИсчисленныеВзносы.ПФРСтраховаяПАВОборот,<br> | РанееИсчисленныеВзносы.ПФРНакопительнаяЕНВДПАВОборот,<br> | РанееИсчисленныеВзносы.ПФРСтраховаяЕНВДПАВОборот,<br> | РанееИсчисленныеВзносы.ПФРПоДополнительномуТарифуПАВОборот,<br> <br> | РанееИсчисленныеВзносы.ПФРНакопительнаяДГПХОборот,<br> | РанееИсчисленныеВзносы.ПФРСтраховаяДГПХОборот,<br> | РанееИсчисленныеВзносы.ПФРНакопительнаяЕНВДДГПХОборот,<br> | РанееИсчисленныеВзносы.ПФРСтраховаяЕНВДДГПХОборот,<br> | РанееИсчисленныеВзносы.ПФРПоДополнительномуТарифуДГПХОборот,<br> <br> | РанееИсчисленныеВзносы.ФССВнебюджетВОборот,<br> | РанееИсчисленныеВзносы.ФФОМСВнебюджетОборот,<br> | РанееИсчисленныеВзносы.ТФОМСВнебюджетОборот,<br> | РанееИсчисленныеВзносы.ПФРНакопительнаяВнебюджетОборот,<br> | РанееИсчисленныеВзносы.ПФРСтраховаяВнебюджетОборот,<br> | РанееИсчисленныеВзносы.ПФРНакопительнаяЕНВДВнебюджетОборот,<br> | РанееИсчисленныеВзносы.ПФРСтраховаяЕНВДВнебюджетОборот,<br> | РанееИсчисленныеВзносы.ПФРПоДополнительномуТарифуВнебюджетОборот<br><br><br>//мов—<br> |ПОМЕСТИТЬ ВТРанееИсчисленныеВзносыПоМесяцам<br> |ИЗ<br> | РегистрНакопления.СтраховыеВзносыИсчисленные.Обороты(<br> | &парамНачалоГода,<br> | &парамКонецМесяцаПериодаРегистрации,<br> | Месяц,<br> | Организация = &парамГоловнаяОрганизация<br> | И (НЕ ФизЛицо В<br> | (ВЫБРАТЬ<br> | СписокСотрудников.ФизЛицо<br> | ИЗ<br> | ВТФизлицаБезОблагаемойБазы КАК СписокСотрудников))<br> | И ФизЛицо В<br> | (ВЫБРАТЬ<br> | СписокСотрудников.ФизЛицо<br> | ИЗ<br> | ВТСписокСотрудников КАК СписокСотрудников)) КАК РанееИсчисленныеВзносы<br> |<br> |ОБЪЕДИНИТЬ ВСЕ<br> |<br> |ВЫБРАТЬ<br> | СтраховыеВзносыИсчисленные.ФизЛицо,<br> | МЕСЯЦ(СтраховыеВзносыИсчисленные.Период),<br> | -СтраховыеВзносыИсчисленные.ФСС,<br> | -СтраховыеВзносыИсчисленные.ФФОМС,<br> | -СтраховыеВзносыИсчисленные.ТФОМС,<br> | -СтраховыеВзносыИсчисленные.ПФРНакопительная,<br> | -СтраховыеВзносыИсчисленные.ПФРСтраховая,<br> | -СтраховыеВзносыИсчисленные.ПФРНакопительнаяЕНВД,<br> | -СтраховыеВзносыИсчисленные.ПФРСтраховаяЕНВД,<br> | -СтраховыеВзносыИсчисленные.ПФРПоДополнительномуТарифу,<br> //мов++<br> | -СтраховыеВзносыИсчисленные.ФССПАВ,<br> | -СтраховыеВзносыИсчисленные.ФФОМСПАВ,<br> | -СтраховыеВзносыИсчисленные.ТФОМСПАВ,<br> | -СтраховыеВзносыИсчисленные.ПФРНакопительнаяПАВ,<br> | -СтраховыеВзносыИсчисленные.ПФРСтраховаяПАВ,<br> | -СтраховыеВзносыИсчисленные.ПФРНакопительнаяЕНВДПАВ,<br> | -СтраховыеВзносыИсчисленные.ПФРСтраховаяЕНВДПАВ,<br> | -СтраховыеВзносыИсчисленные.ПФРПоДополнительномуТарифуПАВ,<br> <br> | -СтраховыеВзносыИсчисленные.ПФРНакопительнаяДГПХ,<br> | -СтраховыеВзносыИсчисленные.ПФРСтраховаяДГПХ,<br> | -СтраховыеВзносыИсчисленные.ПФРНакопительнаяЕНВДДГПХ,<br> | -СтраховыеВзносыИсчисленные.ПФРСтраховаяЕНВДДГПХ,<br> | -СтраховыеВзносыИсчисленные.ПФРПоДополнительномуТарифуДГПХ,<br> <br> | -СтраховыеВзносыИсчисленные.ФССВнебюджет,<br> | -СтраховыеВзносыИсчисленные.ФФОМСВнебюджет,<br> | -СтраховыеВзносыИсчисленные.ТФОМСВнебюджет,<br> | -СтраховыеВзносыИсчисленные.ПФРНакопительнаяВнебюджет,<br> | -СтраховыеВзносыИсчисленные.ПФРСтраховаяВнебюджет,<br> | -СтраховыеВзносыИсчисленные.ПФРНакопительнаяЕНВДВнебюджет,<br> | -СтраховыеВзносыИсчисленные.ПФРСтраховаяЕНВДВнебюджет,<br> | -СтраховыеВзносыИсчисленные.ПФРПоДополнительномуТарифуВнебюджет<br><br><br>//мов—<br> |ИЗ<br> | РегистрНакопления.СтраховыеВзносыИсчисленные КАК СтраховыеВзносыИсчисленные<br> |ГДЕ<br> | СтраховыеВзносыИсчисленные.Регистратор = &Регистратор<br> | И СтраховыеВзносыИсчисленные.Организация = &парамГоловнаяОрганизация<br> | И (НЕ СтраховыеВзносыИсчисленные.ФизЛицо В<br> | (ВЫБРАТЬ<br> | СписокСотрудников.ФизЛицо<br> | ИЗ<br> | ВТФизлицаБезОблагаемойБазы КАК СписокСотрудников))<br> | И СтраховыеВзносыИсчисленные.ФизЛицо В<br> | (ВЫБРАТЬ<br> | СписокСотрудников.ФизЛицо<br> | ИЗ<br> | ВТСписокСотрудников КАК СписокСотрудников)<br> |<br> |ИНДЕКСИРОВАТЬ ПО<br> | Месяц,<br> | ФизЛицо<br> |;<br> |<br> |////////////////////////////////////////////////////////////­////////////////////<br> |ВЫБРАТЬ<br> | РанееИсчисленныеВзносы.ФизЛицо КАК ФизЛицо,<br> | СУММА(ВЫБОР<br> | КОГДА Инвалид.Физлицо ЕСТЬ NULL <br> | ТОГДА РанееИсчисленныеВзносы.ФССОборот<br> | ИНАЧЕ 0<br> | КОНЕЦ) КАК ФССОборот,<br> | СУММА(ВЫБОР<br> | КОГДА Инвалид.Физлицо ЕСТЬ NULL <br> | ТОГДА РанееИсчисленныеВзносы.ФФОМСОборот<br> | ИНАЧЕ 0<br> | КОНЕЦ) КАК ФФОМСОборот,<br> | СУММА(ВЫБОР<br> | КОГДА Инвалид.Физлицо ЕСТЬ NULL <br> | ТОГДА РанееИсчисленныеВзносы.ТФОМСОборот<br> | ИНАЧЕ 0<br> | КОНЕЦ) КАК ТФОМСОборот,<br> | СУММА(ВЫБОР<br> | КОГДА Инвалид.Физлицо ЕСТЬ НЕ NULL <br> | ТОГДА РанееИсчисленныеВзносы.ФССОборот<br> | ИНАЧЕ 0<br> | КОНЕЦ) КАК ФССОборотИнвалида,<br> | СУММА(ВЫБОР<br> | КОГДА Инвалид.Физлицо ЕСТЬ НЕ NULL <br> | ТОГДА РанееИсчисленныеВзносы.ФФОМСОборот<br> | ИНАЧЕ 0<br> | КОНЕЦ) КАК ФФОМСОборотИнвалида,<br> | СУММА(ВЫБОР<br> | КОГДА Инвалид.Физлицо ЕСТЬ НЕ NULL <br> | ТОГДА РанееИсчисленныеВзносы.ТФОМСОборот<br> | ИНАЧЕ 0<br> | КОНЕЦ) КАК ТФОМСОборотИнвалида,<br> | СУММА(ВЫБОР<br> | КОГДА Инвалид.Физлицо ЕСТЬ НЕ NULL <br> | ТОГДА РанееИсчисленныеВзносы.ПФРНакопительнаяОборот + РанееИсчисленныеВзносы.ПФРНакопительнаяЕНВДОборот<br> | ИНАЧЕ 0<br> | КОНЕЦ) КАК ПФРНакопительнаяОборотИнвалида,<br> | СУММА(ВЫБОР<br> | КОГДА Инвалид.Физлицо ЕСТЬ НЕ NULL <br> | ТОГДА РанееИсчисленныеВзносы.ПФРСтраховаяОборот + РанееИсчисленныеВзносы.ПФРСтраховаяЕНВДОборот<br> | ИНАЧЕ 0<br> | КОНЕЦ) КАК ПФРСтраховаяОборотИнвалида,<br> | СУММА(ВЫБОР<br> | КОГДА Инвалид.Физлицо ЕСТЬ NULL <br> | ТОГДА РанееИсчисленныеВзносы.ПФРНакопительнаяОборот<br> | ИНАЧЕ 0<br> | КОНЕЦ) КАК ПФРНакопительнаяОборот,<br> | СУММА(ВЫБОР<br> | КОГДА Инвалид.Физлицо ЕСТЬ NULL <br> | ТОГДА РанееИсчисленныеВзносы.ПФРСтраховаяОборот<br> | ИНАЧЕ 0<br> | КОНЕЦ) КАК ПФРСтраховаяОборот,<br> | СУММА(ВЫБОР<br> | КОГДА Инвалид.Физлицо ЕСТЬ NULL <br> | ТОГДА РанееИсчисленныеВзносы.ПФРНакопительнаяЕНВДОборот<br> | ИНАЧЕ 0<br> | КОНЕЦ) КАК ПФРНакопительнаяЕНВДОборот,<br> | СУММА(ВЫБОР<br> | КОГДА Инвалид.Физлицо ЕСТЬ NULL <br> | ТОГДА РанееИсчисленныеВзносы.ПФРСтраховаяЕНВДОборот<br> | ИНАЧЕ 0<br> | КОНЕЦ) КАК ПФРСтраховаяЕНВДОборот,<br> | СУММА(РанееИсчисленныеВзносы.ПФРПоДополнительномуТарифуОборот) КАК ПФРПоДополнительномуТарифуОборот,<br> //мов++<br> | СУММА(ВЫБОР<br> | КОГДА Инвалид.Физлицо ЕСТЬ NULL <br> | ТОГДА РанееИсчисленныеВзносы.ФССПАВОборот<br> | ИНАЧЕ 0<br> | КОНЕЦ) КАК ФССПАВОборот,<br> | СУММА(ВЫБОР<br> | КОГДА Инвалид.Физлицо ЕСТЬ NULL <br> | ТОГДА РанееИсчисленныеВзносы.ФФОМСПАВОборот<br> | ИНАЧЕ 0<br> | КОНЕЦ) КАК ФФОМСПАВОборот,<br> | СУММА(ВЫБОР<br> | КОГДА Инвалид.Физлицо ЕСТЬ NULL <br> | ТОГДА РанееИсчисленныеВзносы.ТФОМСПАВОборот<br> | ИНАЧЕ 0<br> | КОНЕЦ) КАК ТФОМСПАВОборот,<br> | СУММА(ВЫБОР<br> | КОГДА Инвалид.Физлицо ЕСТЬ НЕ NULL <br> | ТОГДА РанееИсчисленныеВзносы.ФССПАВОборот<br> | ИНАЧЕ 0<br> | КОНЕЦ) КАК ФССПАВОборотИнвалида,<br> | СУММА(ВЫБОР<br> | КОГДА Инвалид.Физлицо ЕСТЬ НЕ NULL <br> | ТОГДА РанееИсчисленныеВзносы.ФФОМСПАВОборот<br> | ИНАЧЕ 0<br> | КОНЕЦ) КАК ФФОМСПАВОборотИнвалида,<br> | СУММА(ВЫБОР<br> | КОГДА Инвалид.Физлицо ЕСТЬ НЕ NULL <br> | ТОГДА РанееИсчисленныеВзносы.ТФОМСПАВОборот<br> | ИНАЧЕ 0<br> | КОНЕЦ) КАК ТФОМСПАВОборотИнвалида,<br> | СУММА(ВЫБОР<br> | КОГДА Инвалид.Физлицо ЕСТЬ НЕ NULL <br> | ТОГДА РанееИсчисленныеВзносы.ПФРНакопительнаяПАВОборот + РанееИсчисленныеВзносы.ПФРНакопительнаяЕНВДПАВОборот<br> | ИНАЧЕ 0<br> | КОНЕЦ) КАК ПФРНакопительнаяПАВОборотИнвалида,<br> | СУММА(ВЫБОР<br> | КОГДА Инвалид.Физлицо ЕСТЬ НЕ NULL <br> | ТОГДА РанееИсчисленныеВзносы.ПФРСтраховаяПАВОборот + РанееИсчисленныеВзносы.ПФРСтраховаяЕНВДПАВОборот<br> | ИНАЧЕ 0<br> | КОНЕЦ) КАК ПФРСтраховаяПАВОборотИнвалида,<br> | СУММА(ВЫБОР<br> | КОГДА Инвалид.Физлицо ЕСТЬ NULL <br> | ТОГДА РанееИсчисленныеВзносы.ПФРНакопительнаяПАВОборот<br> | ИНАЧЕ 0<br> | КОНЕЦ) КАК ПФРНакопительнаяПАВОборот,<br> | СУММА(ВЫБОР<br> | КОГДА Инвалид.Физлицо ЕСТЬ NULL <br> | ТОГДА РанееИсчисленныеВзносы.ПФРСтраховаяПАВОборот<br> | ИНАЧЕ 0<br> | КОНЕЦ) КАК ПФРСтраховаяПАВОборот,<br> | СУММА(ВЫБОР<br> | КОГДА Инвалид.Физлицо ЕСТЬ NULL <br> | ТОГДА РанееИсчисленныеВзносы.ПФРНакопительнаяЕНВДПАВОборот<br> | ИНАЧЕ 0<br> | КОНЕЦ) КАК ПФРНакопительнаяЕНВДПАВОборот,<br> | СУММА(ВЫБОР<br> | КОГДА Инвалид.Физлицо ЕСТЬ NULL <br> | ТОГДА РанееИсчисленныеВзносы.ПФРСтраховаяЕНВДПАВОборот<br> | ИНАЧЕ 0<br> | КОНЕЦ) КАК ПФРСтраховаяЕНВДПАВОборот,<br> | СУММА(РанееИсчисленныеВзносы.ПФРПоДополнительномуТарифуПАВОборот) КАК ПФРПоДополнительномуТарифуПАВОборот,<br> <br> ///////////////////////////////<br> | СУММА(ВЫБОР<br> | КОГДА Инвалид.Физлицо ЕСТЬ НЕ NULL <br> | ТОГДА РанееИсчисленныеВзносы.ПФРНакопительнаяДГПХОборот + РанееИсчисленныеВзносы.ПФРНакопительнаяЕНВДДГПХОборот<br> | ИНАЧЕ 0<br> | КОНЕЦ) КАК ПФРНакопительнаяДГПХОборотИнвалида,<br> | СУММА(ВЫБОР<br> | КОГДА Инвалид.Физлицо ЕСТЬ НЕ NULL <br> | ТОГДА РанееИсчисленныеВзносы.ПФРСтраховаяДГПХОборот + РанееИсчисленныеВзносы.ПФРСтраховаяЕНВДДГПХОборот<br> | ИНАЧЕ 0<br> | КОНЕЦ) КАК ПФРСтраховаяДГПХОборотИнвалида,<br> | СУММА(ВЫБОР<br> | КОГДА Инвалид.Физлицо ЕСТЬ NULL <br> | ТОГДА РанееИсчисленныеВзносы.ПФРНакопительнаяДГПХОборот<br> | ИНАЧЕ 0<br> | КОНЕЦ) КАК ПФРНакопительнаяДГПХОборот,<br> | СУММА(ВЫБОР<br> | КОГДА Инвалид.Физлицо ЕСТЬ NULL <br> | ТОГДА РанееИсчисленныеВзносы.ПФРСтраховаяДГПХОборот<br> | ИНАЧЕ 0<br> | КОНЕЦ) КАК ПФРСтраховаяДГПХОборот, <br>ну и т.д.<br>где на этом куске при заполнении документа расчет страховых взносов 1с выдает сообщение<br>{Документ.РасчетСтраховыхВзносов(3767)}: Ошибка при вызове метода контекста (Выполнить): {(948, 2)}: Синтаксическая ошибка «СУММА(ВЫБОР»<br><<?>>СУММА(ВЫБОР<br> Возврат Запрос.Выполнить().Выгрузить();<br>Знаю, что где-то по хду дела не хватает запятой. Просто уже не вижу, где именно. Народ, посмотрите, пожалуйста свежим взглядом.»

BelikovS

Дата регистрации: 05.03.2007
Сообщений: 1701

Скопируйте запрос в текстовый документ перейдите на 948 строку и посмотрите что там рядом.<br>Еще можно запрос засунуть в консоль запросов и вызвать конструктор — он тоже покажет в какой строке ошибка.

Ivan_Ivanov

Дата регистрации: 06.06.2007
Сообщений: 168

Блин, точно. Спасибо большое за чистку мозгов :-). Еще кучу ошибок таким образом исправила

Показывать по
10
20
40
сообщений

Вот текст запроса

ВЫБРАТЬ
	              |	ЦеныНоменклатурыСрезПоследних.Цена,
	              |	ЦеныНоменклатурыСрезПоследних.Валюта,
	              |	ЦеныНоменклатурыСрезПоследних.ВидЦены,
	              |	ЦеныНоменклатурыСрезПоследних.Номенклатура,
	              |	ЦеныНоменклатурыСрезПоследних.Характеристика
	              |ИЗ
	              |	РегистрСведений.ЦеныНоменклатуры.СрезПоследних КАК ЦеныНоменклатурыСрезПоследних
	              |ГДЕ
	              |	ЦеныНоменклатурыСрезПоследних.ВидЦены В(&ТипЦен)
	              |	И ЦеныНоменклатурыСрезПоследних.Номенклатура В(&Номенлатуры)"

Запрос построено на конструкторе запросов.

Текст ошибки

{Форма.ГлавнаяФорма.Форма(206)}: Ошибка при вызове метода контекста (Выполнить)
	ТабЗначРезультат = Запрос.Выполнить().Выгрузить();
по причине:
{(4, 2)}: Синтаксическая ошибка "ИЗ"
<<?>>ИЗ


  • Вопрос задан

    более трёх лет назад

  • 2216 просмотров

Ошибка синтаксиса языка запроса.
Вам нужно определится с тем, что вы используете. Если работаете с физической таблицей, то источник = РегистрСведений.ЦеныНоменклатуры. Если хотите виртуальную таблицу срезу последних, то даже не обязательно задавать время среза и условие (которое вы запихнули в секцию ГДЕ), но обязательно указать круглые кавычки!

ВЫБРАТЬ
| ЦеныНоменклатурыСрезПоследних.Цена,
| ЦеныНоменклатурыСрезПоследних.Валюта,
| ЦеныНоменклатурыСрезПоследних.ВидЦены,
| ЦеныНоменклатурыСрезПоследних.Номенклатура,
| ЦеныНоменклатурыСрезПоследних.Характеристика
|ИЗ
| РегистрСведений.ЦеныНоменклатуры.СрезПоследних(, ВидЦены В(&ТипЦен) и Номенклатура В(&Номенлатуры)) КАК ЦеныНоменклатурыСрезПоследних»

Пригласить эксперта


  • Показать ещё
    Загружается…

06 июн. 2023, в 20:24

3500 руб./за проект

06 июн. 2023, в 20:08

100 руб./за проект

06 июн. 2023, в 20:05

150 руб./за проект

Минуточку внимания

Я пытаюсь запустить следующий запрос, и я получаю следующую ошибку:

У вас есть ошибка в синтаксисе SQL; проверьте руководство, соответствующее версии вашего сервера MySQL, для правильного синтаксиса для использования рядом с sum (sl.duration) в качестве продолжительности, sum (sl.quantity_loss) как quantity_loss ‘

SELECT 
   lr.uid AS loss_reason_uid,
   gl.uid AS gl_uid,
   lt.uid AS lt_uid,
   SUM(sl.duration * b.marginal_value_downtime) AS value_loss where en.state = 'downtime',
   SUM(sl.quantity_loss * p.marginal_value) as value_loss where en.state != 'downtime',
   SUM(sl.duration) AS duration,
   SUM(sl.quantity_loss) AS quantity_loss,
   COUNT(*) AS count
FROM
    sub_losses AS sl

Любая идея, почему возникает синтаксическая ошибка?

04 дек. 2017, в 11:45

Поделиться

Источник

2 ответа

Это сработало для меня. Спасибо @HoneyBadger за руководство.

SELECT 
    lr.uid AS loss_reason_uid,
        gl.uid AS gl_uid,
        lt.uid AS lt_uid,
        SUM(CASE WHEN en.state = 'downtime' THEN sl.duration * b.marginal_value_downtime ELSE sl.quantity_loss * p.marginal_value END) AS value_loss,
        SUM(sl.duration) AS duration,
        SUM(sl.quantity_loss) AS quantity_loss,
        COUNT(*) AS count
FROM
    sub_losses AS sl

aryan87
04 дек. 2017, в 10:01

Поделиться

ПОПРОБУЙТЕ ЭТО: За исключением вышеприведенных комментариев не разрешено использовать одни и ALIAS же ALIAS или COLUMN NAME более одного раза в одном блоке запроса, поэтому я дал value_loss1 чтобы сделать уникальным.

SELECT 
   lr.uid AS loss_reason_uid,
   gl.uid AS gl_uid,
   lt.uid AS lt_uid,
   SUM(CASE WHEN en.state = 'downtime' THEN (sl.duration * b.marginal_value_downtime) ELSE 0 END) AS value_loss,
   SUM(CASE WHEN en.state != 'downtime' THEN (sl.quantity_loss * p.marginal_value) ELSE 0 END) AS value_loss1,
   SUM(sl.duration) AS duration,
   SUM(sl.quantity_loss) AS quantity_loss,
   COUNT(*) AS count
FROM sub_losses AS sl
GROUP BY lr.uid,
         gl.uid,
         lt.uid

Susang
04 дек. 2017, в 09:15

Поделиться

Ещё вопросы

  • 1Объявление массива байтов в качестве открытого члена
  • 1Шаблон наблюдателя в Android
  • 0Показывать публичные публикации пользователя на сайте
  • 0ASP.NET API Controller возвращает XMLHttpRequest не может загрузить URL Неверный код состояния HTTP 404
  • 0Изменение данных контроллера с помощью директив AngularJS
  • 0Показать скрытый div при отправке формы (JavaScript и PHP)
  • 0Почему мой URL-адрес angularjs отличается?
  • 1Основной конец этой ассоциации должен быть явно настроен
  • 0Angularjs проблема $ http.get не работает
  • 0Резервное копирование базы данных Mysql с помощью сценария оболочки — для bind-адреса установлено значение localhost
  • 0Отправить Push-уведомление на все токены в базе данных MySql
  • 1SciChart График разрыва
  • 0как скользить изображения в угловых JS?
  • 1Сборный размер Unity
  • 1Является ли создание и присвоение значений List <T> потокобезопасным?
  • 0Лучший подход к созданию приложения киоска с представлениями, которые меняются по таймеру
  • 0Как сделать так, чтобы изображение всегда загружалось в центре страницы?
  • 0Компиляция и использование OpenCV
  • 1Выбор по индексу внутри выбора d3
  • 0‘SQLSTATE [HY093], я неправильно поставил запятую?
  • 0как перейти на страницу без углов в транспортире? [Дубликат]
  • 0показать загруженное изображение, прежде чем нажать на кнопку отправить
  • 1TypeError с помощью json.load () из пакета сборки при развертывании приложения
  • 0Поведение CodeIgniter, конструкторы и маршруты
  • 1Apk не устанавливается на Oreo
  • 0Использование CONCAT с оператором CASE работает некорректно
  • 1Как рассчитать выход нейронной сети?
  • 0Векторы разного размера в зависимости от ввода пользователя
  • 0Как я могу перезагрузить один раз, используя window.location.reload?
  • 1Могу ли я отформатировать тип данных TIME на JavaDB?
  • 0Сумма столбцов с использованием соединения
  • 0Выбор строки не сохраняется на всех страницах разбиения на страницы в ng-grid?
  • 0Получение значения CSS и его обновление в SQL
  • 0Angular-Block-UI не работает в распределении — не удается найти функцию модуля (угловая)
  • 1Python selenium ждет загрузки страницы без условия
  • 0Выберите, где значение может быть нулевым или нет
  • 0удалить событие тега в теге jquery
  • 0MySQL — привязка сотрудников к счету №
  • 1Найти корень производной абсолютного значения комплексного числа в симпы
  • 1Генерация пары ключей RSA на стороне клиента в приложении Google Web Toolkit через Google App Engine с библиотекой gwt-crypto
  • 0C # UWP Форма входа, проверяющая учетные данные в удаленной базе данных MySQL
  • 1Гистограмма путем группировки значений в Python
  • 0Ошибка компиляции PHP при создании представлений и контроллеров с использованием Gii в YII2
  • 1Украшение именованных компонентов в виндзоре
  • 0Ключ API Google MAP в приложении Angular
  • 0Как я могу читать не символы, такие как арабские слова в PHP
  • 0Как поместить <div> в текст внутри <p> в html + css?
  • 1генерировать случайное число с плавающей точкой в C #
  • 0высокая диаграмма с фильтрацией диапазона дат
  • 0Авто Требуется в PHP

Сообщество Overcoder

Понравилась статья? Поделить с друзьями:
  • Синтаксическая ошибка справочники найтипокоду
  • Синтаксические ошибки русского языка могут быть связаны
  • Синтаксическая ошибка справочники видыцен доступныевидыцен
  • Синтаксические ошибки программы это
  • Синтаксические ошибки причастный оборот