Имя: Пароль:
1C
 
Пакетные запросы: как переделать запрос в пакетный?
0 DenYuliya
 
15.12.22
14:02
Всем добрый день.
Безумно неловко таке простые вещи спрашивать, но - не могу понять, что имеется в виду под "Переделать запрос под пакетный", можете подсказать, пожалуйста?
Задача следующая: есть спр. "Сотрудники", есть несколько организаций в рамках одной базы, в каждой организации по сотруднику ведутся разные документы. Сотрудники в разное время могли работать в разных организациях (т.е. у сотрудника1 в период Х может быть 10 разных документов в организации1, а потом у этого же сотрудника1 в период У может быть еще 5 документов уже в организации2).
Надо выбрать все документы по сотрудникам, с датой рождения в выбранный период, с отбором по организации. Например, "все документы всех сотрудников с датой рождения 01.01.2001, по Организации1". А потом эти документы обработать программно.

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

Честно говоря, не скажу, что часто этм пользовалась, обычно хватало временных таблиц. И есть у меня подозрение, что исправлений тут на 10 минут, просто я туплю. Можете ткнуть носом, пожалуйста, в какую сторону смотреть?
Вот такой запрос у меня сейчас: ВТ Сотрудники, ВТ Документы (в которой собраны документы), потом запрос пакета, собирающий предыдущие 2 ВТ в единый результат (если в конструкторе смотреть на вкладке "Пакет запросов".
Разве это не "пакетный запрос"? Что сделать-то надо? Разделить их просто на 2 запроса без использования ВТ? Но я смотрю по примерам, в пакетных запросах не используется соединение, ведь так? А как тогда связать между собой эти запросы?
Было так:


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

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    Документ1.Ссылка КАК Ссылка,
    Документ1.Дата КАК Дата,
    Документ1.ИмяСотрудника КАК ИмяСотрудника
ПОМЕСТИТЬ ВТ_Документы
ИЗ
    Документ.Документ1 КАК Документ1
ГДЕ
    НЕ Документ1.ПометкаУдаления

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    Документ2.Ссылка,
    Документ2.Дата,
    Документ2.ИмяСотрудника
ИЗ
    Документ.Документ2 КАК Документ2
ГДЕ
    НЕ Документ2.ПометкаУдаления
;

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

УПОРЯДОЧИТЬ ПО
    Дата";
1 Гипервизор
 
15.12.22
14:06
(0) У вас и есть пакетный запрос. Может речь шла о добавлении итогов по сотрудникам, чтобы обходить выборку по группировкам?
2 DenYuliya
 
15.12.22
14:30
(1)  а вот хз.
3 Kassern
 
15.12.22
14:37
(0) Смотря, что вы вкладываете в понятие "пакетный запрос"
На вскидку могу предположить 2 варианта:
1) Выполнять запрос в цикле по ограниченной таблице. К примеру отобрать первые 10000, выполнить манипуляции и так в цикле, пока выборка не закончится.
2) Сформировать запрос с несколькими пакетами. Далее Запрос.ВыполнитьПакет() и получаем нужный результат, так примерно работает заполнения печатных форм, несколько результатов (для шапки, для тч и т.д.).
4 DenYuliya
 
15.12.22
14:41
(3) Скорее вариант 2, запрос в цикле- вселенское зло).
Тэк...А чем у меня не "запрос с  несколькими пакетами"? У меня их  2, уже несколько). Или надо Документ1 вынести в один пакет, документ2 - во второй, справочник Сотрудники - в третий?
5 mistеr
 
15.12.22
14:46
(2) А препод немой? Почему вопрос к нам, а не к нему?
6 DenYuliya
 
15.12.22
14:48
(5) а это не препод). Задавать тупые вопросы на форуме менее черевато, чем начальнику)
7 Kassern
 
15.12.22
14:49
(4) "запрос в цикле- вселенское зло" - просто нужно уметь их готовить. Иногда это самый оптимальный вариант решения задачи.
8 DenYuliya
 
15.12.22
14:53
(7) всея рекомендации 1С гласят, что зло). Всякие там "рекомендации по оптимизации кода" и "как никогда делать нельзя".
9 Kassern
 
15.12.22
14:55
(7) + если посмотрите в типовых конфигурациях то вполне можете найти следующую конструкцию:

    Пока Истина Цикл
        Попытка
            Результат = Запрос.Выполнить();// Чтение вне транзакции, возможно появление ошибки.

                                            // Could not continue scan with NOLOCK due to data movement

                                            // в этом случае нужно повторить попытку чтения.

            Прервать;
        Исключение
            КоличествоПопыток = КоличествоПопыток + 1;
            Если КоличествоПопыток = 5 Тогда
                ВызватьИсключение;
            КонецЕсли;
        КонецПопытки;
    КонецЦикла;
10 Kassern
 
15.12.22
14:57
Так же бывают различные разузлования номенклатуры, что так же в циклах реализуют. Где-то даже пример видел на ИТС с Выбрать первые и запросом в цикле. Мол как раз в плане оптимизации, чтобы не получать за раз огромную таблицу.
11 DenYuliya
 
15.12.22
15:04
(10) возьму на заметку, и все таки - если исходить из варианта 2 "Сформировать запрос с несколькими пакетами. Далее Запрос.ВыполнитьПакет() "  - у меня же и так пакетный запрос? Или я люто туплю и чего-то не хватает?
Вероятно, действительно речь шла не о исправлении текста запроса, а о дальнейшей его обработке.
У меня сейчас стандартно:

РезультатЗапроса = Запрос.Выполнить().Выгрузить();

Для Каждого Строка Из РезультатЗапроса  Цикл
//тут обрабатывается каждый документ
КонецЦикла
12 Asmody
 
15.12.22
15:05
Пакетный запрос хорош тем, что:
а) его можно выполнять по частям;
б) можно вытащить данные из временных таблиц.

Для этого вы берете МенеджерВременныхТаблиц, закидываете туда часть запроса, который, например, создаёт временные таблицы.
Затем этот же МВТ цепляете к другому запросу и пользуетесь в нём уже сформированными ВТ.
Ну и к самим ВТ можно через него обратиться, см. ВременнаяТаблицаЗапроса в СП
13 PLUT
 
15.12.22
15:07
(12) и в отладчике из МВТ очень удобно смотреть временные таблицы с помошью заклинания

МВТ.Таблицы["имяВТ"].ПолучитьДанные().Выгрузить()

и кнопка F2 (показать в отдельном окне)

аминь
14 Asmody
 
15.12.22
15:08
Не совсем корректно написал. Надо так: "Для этого вы берете МенеджерВременныхТаблиц, цепляете его к объекту Запрос, куда закидываете часть запроса, которая, например, создаёт временные таблицы."
15 Asmody
 
15.12.22
15:09
Короче, МВТ позволяет "таскать" ВТ между запросами. В некоторых тяжёлых случаях помогает.
16 Kassern
 
15.12.22
15:13
(12) (15) Погодите, как пакетный запрос связан с МенеджерВременныхТаблиц? Можно ведь и без временных таблиц создать пакетный запрос и выполнить его по пакетно.
17 Chai Nic
 
15.12.22
15:15
(16) По-моему, в ранних версиях восьмерки пакетные запросы не выполнялись, если не задан менеджер временных таблиц.
18 DenYuliya
 
15.12.22
15:15
(1) в итоге оказалось, что вы были правы. Речь шла о добавлении итогов по сотруднику.
(10) оказывается, имелось в виду добавить итоги по сотрудникам, и по ним в цикле обрабатывать документы
19 DenYuliya
 
15.12.22
15:16
(16) а у меня и так пакетный запрос с ВТ. Изначально так и было. Только итогов не было
20 DenYuliya
 
15.12.22
15:35
(1) а "добавление итогов по сотрудникам, чтобы обходить выборку по группировкам" для такой цели делается через "Общие итоги" (хотя там вроде бы  числовые значения, это, думаю, не то), или через "группировочное поле" (в СКД на вкладке "Итоги")?
21 Гипервизор
 
15.12.22
15:43
(20) У вас сделано на СКД? В запросе через "Общие итоги" на странице "Итоги" конструктора запросов, а может вы вообще текст запроса пишете без конструктора. )
А где в СКД вкладка "Итоги"?
22 DenYuliya
 
15.12.22
15:57
(21) прошу прощения про очипятку, "СКД" = "Конструктор запроса", конечно же
23 Гипервизор
 
15.12.22
16:04
(22) Тьфу, я сам ерунду написал, не нужны вам общие итоги, на странице "Итоги" просто добавьте группировку по сотруднику.
24 DenYuliya
 
15.12.22
16:16
(23) Ну вот, я сначала так и сделала.


ВЫБРАТЬ
    Документ1.Ссылка КАК Ссылка,
    Документ1.Дата КАК Дата,
    Документ1.ИмяСотрудника КАК ИмяСотрудника
ПОМЕСТИТЬ ВТ_Документы
ИЗ
    Документ.Документ1 КАК Документ1
ГДЕ
    НЕ Документ1.ПометкаУдаления

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    Документ2.Ссылка,
    Документ2.Дата,
    Документ2.ИмяСотрудника
ИЗ
    Документ.Документ2 КАК Документ2
ГДЕ
    НЕ Документ2.ПометкаУдаления

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    Документ3.Ссылка,
    Документ3.Дата,
    Документ3.ИмяСотрудника
ИЗ
    Документ.Документ3 КАК Документ3
ГДЕ
    НЕ Документ3.ПометкаУдаления
;

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


Потом делаю так:

РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);
Пока Выборка.Следующий Цикл              
     ДетальныеЗаписи = Выборка.Выбрать();        
    Пока ДетальныеЗаписи.Следующий() Цикл
        // Заполнение
    КонецЦикла;
КонецЦикла;  

Иии... у меня вываливается с ошибкой ""
Хотя если выгружать в ТЗ, данные есть, корректные

Где я неправильно делаю?
25 Said_We
 
15.12.22
16:18
(18) Если в документе несколько сотрудников в табличной части, то правильнее группировать по документам и обрабатывать документ сразу по всем сотрудникам из табличной части. Под обработкой же понимается внесение изменений в документ по сотрудникам?
Лучше одни раз записать документ по 100 сотрудникам, чем записать 100 раз один и тот же документ, меняя по чуть чуть.
26 DenYuliya
 
15.12.22
16:21
В продолжение к (24):
Вываливается с ошибкой "Поле объекта не обнаружено (Следующий)"
27 DenYuliya
 
15.12.22
16:21
(25) в документе один сотрудник,и никакой табличной части.
28 Said_We
 
15.12.22
16:22
Следующий() это метод, а не поле - первый цикл смотри.
29 DenYuliya
 
15.12.22
16:23
(28) ааа, я тупень, ну конечно, скобки после Следующий() проимела((((. Вот уж правда, "спешка нужна только при ловле блох"
30 Said_We
 
15.12.22
16:26
(29) ВыборкаПоСотруднику = РезультатЗапроса.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам, "ИмяСотрудника");
Я всегда указываю, что за группировка.
31 Гипервизор
 
15.12.22
16:33
(30) Привычка?
32 DenYuliya
 
15.12.22
16:46
(30) Зачем? В плане, вариант (31), или есть разница?
33 Said_We
 
15.12.22
17:00
(31) УГУ...
34 Said_We
 
15.12.22
17:10
Можно же написать запрос так:

Выбрать
    т.ПолеА как ПолеА,
    т.ПолеБ как ПолеБ
ИЗ
    т как т
УПОРЯДОЧИТЬ ПО
    2,
    1

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

Просто привычка.