Имя: Пароль:
1C
1C 7.7
v7: Оптимизация запроса...
,
0 bananan
 
04.02.13
11:20
Есть такой код:
Процедура Сформировать(Пар)
   ТекстЗапроса = "//{{ЗАПРОС(СписокСотрудников)
   |Период с {ДатаАктуальности} по {ДатаАктуальности};
   |Сотр = Справочник.Сотрудники.ТекущийЭлемент;
   |Фир = Справочник.Сотрудники.Фирма;
   |Оклад = Справочник.Сотрудники.Оклад;
   |КвоЛьгот = Справочник.Сотрудники.КвоЛьгот;
   |Тариф = Справочник.Сотрудники.Тариф;
   |Пенсионер = Справочник.Сотрудники.Пенсионер;
   |Инвалид = Справочник.Сотрудники.Инвалид;
   |Должность = Справочник.Сотрудники.МестоРаботы;
   |Ставка = Справочник.Сотрудники.Ставка;
   |Совместитель = Справочник.Сотрудники.ТипСотрудника;
   |ДатаПриема = Справочник.Сотрудники.ДатаПриема;
   |ДатаУвольнения = Справочник.Сотрудники.ДатаУвольнения;
   |Условие(Фир=Фирма);
   |Условие (Число(Сотр.Родитель.Код) <> 0);
   |Условие(Сотр в ВыбСотрудник);
   |Условие(ДатаПриема<>Дата(0));
   |Условие(ДатаПриема<=ДатаАктуальности);";
   Если фОсновные=0 Тогда
       ТекстЗапроса=ТекстЗапроса+"
       |Условие(Совместитель=1);";
   КонецЕсли;
   Если фСовместители=0 Тогда
       ТекстЗапроса=ТекстЗапроса+"
       |Условие(Совместитель=0);";
   КонецЕсли;
   Если Пар=1 Тогда
       ТекстЗапроса=ТекстЗапроса+"
       |Группировка Сотр Упорядочить По Сотр.Наименование;";
   Иначе
       ТекстЗапроса=ТекстЗапроса+"
       |Группировка Сотр Упорядочить По Сотр.Код;";
   КонецЕсли;
   ТекстЗапроса=ТекстЗапроса+"
   |Функция Окл = Сумма(Оклад);
   
   //|Функция Раб = Сумма(1) КОГДА ( (ДатаПриема<>Дата(0)) и (ДатаПриема<=ДатаАктуальности) и (ДатаЧисло(Запрос.ДатаУвольнения)<>0) и (Запрос.ДатаУвольнения<=ДатаАктуальности)  ) ;
   
   |Функция Тар = Сумма(Тариф);";
         
   
   
   Запрос = СоздатьОбъект("Запрос");
   Если Запрос.Выполнить(ТекстЗапроса)=0 Тогда
       Возврат;
   КонецЕсли;

   Таб = СоздатьОбъект("Таблица");

   Таб.ВывестиСекцию("Шапка|Основная");
   Если фУволенные=1 Тогда
       Таб.ПрисоединитьСекцию("Шапка|Увольнение");
   КонецЕсли;
   Если (фОсновные=1) и (фСовместители=1) Тогда
       Таб.ПрисоединитьСекцию("Шапка|Совместитель");
   КонецЕсли;

   Кво = 0;
   Пока Запрос.Группировка("Сотр")=1 Цикл
       Состояние( "Обработка " + Запрос.Сотр);
       
       Если Запрос.Сотр.ЭтоГруппа() = 1 Тогда
           
         Запрос_=СоздатьОбъект("ODBCRecordset");    
         ТекстЗапроса = "    
         |SELECT COUNT(*) as Кво
         |FROM $Справочник.Сотрудники Сотр
         |WHERE Сотр.ID IN (SELECT Val FROM #tmpSotr)
         |AND $Сотр.ДатаПриема> :Дат1
         |AND $Сотр.ДатаПриема<= :ДатаАктуальности
         |AND  ($Сотр.ДатаУвольнения = '01.01.1753' or  $Сотр.ДатаУвольнения>= :ДатаАктуальности )
         |";                              
         Запрос_.УстановитьТекстовыйПараметр("Дат1", Дата("01.01.1989"));  
         Запрос_.УстановитьТекстовыйПараметр("ДатаАктуальности", ДатаАктуальности+1);  
         Запрос_.УложитьСписокОбъектов(Запрос.Сотр.ТекущийЭлемент(), "#tmpSotr","Сотрудники");  
         тЗанято = Запрос_.ВыполнитьСкалярный(ТекстЗапроса);
         ПоШтату =  Запрос.Сотр.ПоШтату;          
         ФиксДан = Шаблон("Занято: [тЗанято] \ По штату: [Запрос.Сотр.ПоШтату] \ Вакантно: [Запрос.Сотр.ПоШтату-тЗанято]");
         Если фУволенные=0 Тогда
             Если тЗанято = 0 Тогда
                 продолжить;
             Конецесли;    
         Конецесли;    
         
         
         Таб.ВывестиСекцию("Группа|Основная");
         Если фУволенные=1 Тогда
             Таб.ПрисоединитьСекцию("Группа|Увольнение");    
         Конецесли;
         Если (фОсновные=1) и (фСовместители=1) Тогда
           Таб.ПрисоединитьСекцию("Группа|Совместитель");
       КонецЕсли;
       Иначе    
       
       Если (фУволенные=0) и (ДатаЧисло(Запрос.ДатаУвольнения)<>0) и (Запрос.ДатаУвольнения<=ДатаАктуальности) Тогда
           Продолжить;
       КонецЕсли;
       Кво = Кво + 1;
       //ОснПенс = ?(Запрос.Сотр.Пенсионер=1,"+","");
       //ОснИнв = ?(Запрос.Сотр.Инвалид=1,"+","");
       ОснПенс = ?(Запрос.Пенсионер=1,"+","");
       ОснИнв = ?(Запрос.Инвалид=1,"+","");
       Таб.ВывестиСекцию("Сотрудник|Основная");
       Если фУволенные=1 Тогда
           Если (ДатаЧисло(Запрос.ДатаУвольнения)<>0) и (Запрос.ДатаУвольнения<=ДатаАктуальности) Тогда
               ДатаУвольнения = Формат(Запрос.ДатаУвольнения,"ДДММГГ");
           Иначе
               ДатаУвольнения = "";
           КонецЕсли;
           Таб.ПрисоединитьСекцию("Сотрудник|Увольнение");
       КонецЕсли;
       Если (фОсновные=1) и (фСовместители=1) Тогда
           ОснСовм = ?(Запрос.Совместитель=1,"+","");
           Таб.ПрисоединитьСекцию("Сотрудник|Совместитель");
       КонецЕсли;
       КонецЕсли;
       
   КонецЦикла;

   Таб.ВывестиСекцию("Дно|Основная");
   Если фУволенные=1 Тогда
       Таб.ПрисоединитьСекцию("Дно|Увольнение");
   КонецЕсли;
   Если (фОсновные=1) и (фСовместители=1) Тогда
       Таб.ПрисоединитьСекцию("Дно|Совместитель");
   КонецЕсли;

   Таб.Опции(0,0,0,0);
   Таб.ТолькоПросмотр(Константа.ФлагЗащитыТаблиц);
   Таб.Показать("Список сотрудников");

КонецПроцедуры

Понято, что вызов запроса в цикле - не лучший вариант, если не скзать хуже...
Так вот не могу сообразить как это сделать в одном запросе?
В даном коде первый (верхний) запрос выбирает данные из справочника сотрудники, а второй (внутренний, тот что в цикле) - суммирует к-во ставок у сотрудников конкретного подразделения
1 Mikeware
 
04.02.13
11:22
на третий круг?
2 Aleksey
 
04.02.13
11:23
(0) Работает, не трожь
3 bananan
 
04.02.13
11:27
(2) Работать - конечно же работает, но мягко говоря, некрасивый код у этого скрипта...
Как бы это сделать в одном запросе (стандартном либо 1С++)?
4 Mikeware
 
04.02.13
11:28
(3) ты не поверишь...
нужно написать запрос, который выбирает все требуемые данные...
5 bananan
 
04.02.13
11:30
(4) Верю. Но вот не пойму как это сделать...
Неделю был на больничном дома (ангина) и периодически в голове всплывал этот запрос, но так ничего нормального в голову не пришло...
6 viktor_vv
 
04.02.13
11:34
(5) Ну заготовка у тебя есть, там где по группе, делай по всем, группу в отдельное поле выведи и без суммирования, результат засунь в индексированную таблицу, группировуй ее и воводи.
Вероятно буду проблемы с вложенными группами.
Но в принципе при известном макисмальном уровен вложенности справочника можно.
7 chelentano
 
04.02.13
11:35
(6) даже не пытайся что-то объяснять, тут сложный случай :)
(0) уменьшить свою з/п у руководства уже просил?
8 bananan
 
04.02.13
11:38
(6) Как скрипт (и оба запросы) работает сейчас - прексрасно понимаю. Но вот как это сделать в одном запросе - голова не варит..
(6) по группе..      |Группировка Сотр Упорядочить По Сотр.Наименование;"; это имеется ввиду или как?
9 sapphire
 
04.02.13
11:39
(1) Опять он :)
10 bananan
 
04.02.13
11:41
+(8) вся загвоздка в подразделении, если просто просуммировать к-во ставок у сотрудников - будет к-во ставок на фирме, а надо иметь количество ставок в каждом подразделении фирмы
11 viktor_vv
 
04.02.13
11:42
(8) Заготовка вот

       Запрос_=СоздатьОбъект("ODBCRecordset");    
         ТекстЗапроса = "    
         |SELECT COUNT(*) as Кво
         |FROM $Справочник.Сотрудники Сотр
         |WHERE Сотр.ID IN (SELECT Val FROM #tmpSotr)
         |AND $Сотр.ДатаПриема> :Дат1
         |AND $Сотр.ДатаПриема<= :ДатаАктуальности
         |AND  ($Сотр.ДатаУвольнения = '01.01.1753' or  $Сотр.ДатаУвольнения>= :ДатаАктуальности )
         |";
12 bananan
 
04.02.13
11:45
(11) C этой стороны я к задаче и не подходил... Попробую
13 viktor_vv
 
04.02.13
11:45
(11)+  Выкинь оттуда count добавь свои реквизиты, как в черном запросе и добавь поле родителя

|SELECT
|Сотр.ParentID as [Родитель $Справочник.Сотрудники]
         |FROM $Справочник.Сотрудники Сотр

и вперед.
14 chelentano
 
04.02.13
11:46
(8) "голова не варит" - да поняли уже
15 viktor_vv
 
04.02.13
11:54
Хотя тебе проще выкинуть прямой запрос, и добавить функцию в твой обычный запрос и все.

  |ДатаУвольнения = Справочник.Сотрудники.ДатаУвольнения;
  |Функция КолСотр = СчЁтчик();
   |Условие(Фир=Фирма);
16 bananan
 
04.02.13
11:54
(14) сообразительный ты
17 bananan
 
04.02.13
11:55
(15) что-то подобное мне в голову прихоидило, но как в функции считать к-во ставок в одном подраздеолении?
18 viktor_vv
 
04.02.13
11:57
(17) Не боись, на уровне

   Пока Запрос.Группировка("Сотр")=1 Цикл
       Состояние( "Обработка " + Запрос.Сотр);
       
       Если Запрос.Сотр.ЭтоГруппа() = 1 Тогда
           КолСотр = Запрос.КолСотр ;

оно само посчитается.
19 viktor_vv
 
04.02.13
11:58
(18)+ Ты ж все равно в прямом считаешь только количество записей (сотрудников) попавших в условия выборки.
20 bananan
 
04.02.13
12:00
(18(19) это мне уже совсем понятно - сейчас так и попробую
21 bananan
 
04.02.13
12:07
Даже не вериться (как все просто) в цикле убрал прямой запрос и вызвал функцию - и ВСЕ.