Имя: Пароль:
1C
1C 7.7
v7: Пишу прямой запрос - получается кривой. Выпрямим?
0 Андрей_Андреич
 
naïve
26.09.12
08:21
Пытаюсь сделать Update таблицы. При этом рекурсивно к этой же таблице обращаюсь. Не получается. Если сделать копию таблицы и обращаться к ней - все ОК. Помогите разобраться - оно невозможно в принципе или я истинный 1Сник (тупой и ленивый)?
1 Андрей_Андреич
 
naïve
26.09.12
08:23
Собственно текст запроса
   |Update "+ТаблицаГрупп+"
   |Set
   |Сортировка = Rtrim(ДопТаблица.Сортировка)+RTrim(ТаблицаГрупп.Сортировка)
   |From "+ТаблицаГрупп+" ТаблицаГрупп
   |Left Join "+ТаблицаГрупп+" ДопТаблица (NoLock) On ТаблицаГрупп.ParentId = ДопТаблица.Id
   |Where ТаблицаГрупп.Уровень=0
2 vde69
 
26.09.12
08:26
небось рекурсия в транзакции???
3 Андрей_Андреич
 
naïve
26.09.12
08:29
(2) Да уже рекурсию выбросил - без всяких циклов не разу не выполняется. Тупой отчет. Не понравилось как иерархия групп обрабатывается - решил переписать. Ну и встрял там же, где сто лет назад.
4 Андрей_Андреич
 
naïve
26.09.12
08:30
Если сделать копию таблицы - выполняется
   |Select ID, ParentId, Сортировка Into "+ДопТаблица+" From "+ТаблицаГрупп+" Where Уровень = @MaxLevel
   |Update "+ТаблицаГрупп+"
   |Set
   |Сортировка = Rtrim(ДопТаблица.Сортировка)+RTrim(ТаблицаГрупп.Сортировка)
   |From "+ТаблицаГрупп+" ТаблицаГрупп
   |Left Join "+ДопТаблица+" ДопТаблица (NoLock) On ТаблицаГрупп.ParentId = ДопТаблица.Id
   |Where ТаблицаГрупп.Уровень=0
5 trad
 
26.09.12
08:50
что бы запрос из (1) алгоритмически соответствовал запросу из (4) он должен быть таким:
|Update "+ТаблицаГрупп+"
|Set
|Сортировка = Rtrim(ДопТаблица.Сортировка)+RTrim(ТаблицаГрупп.Сортировка)
|From "+ТаблицаГрупп+" ТаблицаГрупп
|Left Join "+ТаблицаГрупп+" ДопТаблица (NoLock) On ТаблицаГрупп.ParentId = ДопТаблица.Id And ДопТаблица.Уровень = @MaxLevel
|Where ТаблицаГрупп.Уровень=0
6 Андрей_Андреич
 
naïve
26.09.12
08:55
(5) сейчас попробую - вариантов кучу перебрал естественно. может такого и не было
7 Андрей_Андреич
 
naïve
26.09.12
08:57
(5) вигвам
8 Андрей_Андреич
 
naïve
26.09.12
09:00
(5) то бишь не работает
9 vde69
 
26.09.12
09:01
(3) ты не рекурсия а транзакцию выкини.

проблемма в уровне изоляции разрешающем грязное чтение в транзакции...
10 Андрей_Андреич
 
naïve
26.09.12
09:06
(9) Тупой, вашбродь. Где транзвкция которую выкинуть?
11 vde69
 
26.09.12
09:09
(10) покажи полный код и от куда вызываешь (обработка, документ...)
12 Андрей_Андреич
 
naïve
26.09.12
09:11
(11) Куча мусора - приведу в порядок и выложу. А на словах принцип нельзя?
13 Андрей_Андреич
 
naïve
26.09.12
09:14
Функция глСортировкаПоИерархии2(ИмяТаблицы,НаименованиеПоля,НаименованиеСправочника,СуммируемыеПоля="") Экспорт
   Перем ТекстЗапроса, ТаблицаГрупп, ДопТаблица;
   ДопТаблица="[##"+глПолучитьGUID()+"]";
   ТаблицаГрупп="[##"+глПолучитьGUID()+"]";
   ТекстЗапроса="Set NoCount OFF
   |Declare @MaxLevel Integer
   |Select Номенклатура.Id, Номенклатура.ParentId
   |, Cast(0 As Integer) Уровень
   |, Sum(ИмяТаблицы.Себестоимость) Себестоимость
   |, Sum(ИмяТаблицы.Количество) Количество
   |, Sum(ИмяТаблицы.ПроданоНаСумму) ПроданоНаСумму
   |Into "+ТаблицаГрупп+"
   |From "+ИмяТаблицы+" ИмяТаблицы (NoLock)
   |Left Join $Справочник.Номенклатура Номенклатура (NoLock) On ИмяТаблицы.Товар_ParentId=Номенклатура.Id
   |Group By Номенклатура.ID, Номенклатура.ParentId
   |Set @MaxLevel=1
   |
   |While 1=1 Begin
   |Insert Into "+ТаблицаГрупп+"
   |Select Номенклатура.Id, Номенклатура.ParentId
   |, Cast(@MaxLevel As Integer) Уровень
   |, Sum(ТаблицаГрупп.Себестоимость) Себестоимость
   |, Sum(ТаблицаГрупп.Количество) Количество
   |, Sum(ТаблицаГрупп.ПроданоНаСумму) ПроданоНаСумму
   |From "+ТаблицаГрупп+" ТаблицаГрупп (NoLock)
   |Inner Join $Справочник.Номенклатура Номенклатура (NoLock) On ТаблицаГрупп.ParentId=Номенклатура.Id
   |Where Уровень=@MaxLevel-1
   |Group By Номенклатура.ID, Номенклатура.ParentId
   |
   |    If @@RowCount=0 Begin
   |        Break
   |    END
   |    Set @MaxLevel=@MaxLevel+1
   |END
   |
   |Alter Table "+ТаблицаГрупп+"
   |Add Сортировка Char(500), Code Char(7)
   |Update "+ТаблицаГрупп+"
   |Set
   |Уровень = 0
   |,Сортировка = Номенклатура.Descr, Code = Номенклатура.Code
   |From "+ТаблицаГрупп+" ТаблицаГрупп (NoLock)
   |Left Join $Справочник.Номенклатура Номенклатура On ТаблицаГрупп.Id = Номенклатура.Id
   |Update "+ТаблицаГрупп+"
   |Set Уровень=1
   |, Сортировка=LTrim(Str(1))+RTrim(Сортировка)
   |From "+ТаблицаГрупп+" Where ParentId = '     0   '
   |
   |Set @MaxLevel=1
   |
   |While 1=1 Begin
   //|Select ID, ParentId, Сортировка Into "+ДопТаблица+" From "+ТаблицаГрупп+" Where Уровень = @MaxLevel
   |Update "+ТаблицаГрупп+"
   |Set
   |Сортировка = Rtrim(ДопТаблица.Сортировка)+RTrim(ТаблицаГрупп.Сортировка)
   |From "+ТаблицаГрупп+" ТаблицаГрупп
   |Left Join "+ТаблицаГрупп+" ДопТаблица (NoLock) On ТаблицаГрупп.ParentId = ДопТаблица.Id And ДопТаблица.Уровень = @MaxLevel
   |Where ТаблицаГрупп.Уровень=0
   //|Where ДопТаблица.Уровень = @MaxLevel
   //|    If @@RowCount=0 Begin
   |        Break
   //|    END
   |    Set @MaxLevel=@MaxLevel+1
   |END
   |
   |";
   ТЗ=СоздатьОбъект("ТаблицаЗначений");
   Попытка
       РадугаЗапрос.ВыполнитьИнструкцию(ТекстЗапроса,ТЗ);          
   Исключение
       Предупреждение("Произошла ошибка при выполнении запроса (Создание таблицы )!!!");
       Текст=СоздатьОбъект("Текст");
       Текст.ДобавитьСтроку(ТекстЗапроса);
       Текст.Показать("11");
       Сообщить(ОписаниеОшибки());
       Возврат "";
   КонецПопытки;
   ТекстЗапроса="
   |Select Id [Товар $Справочник.Номенклатура] , ParentId [Группа $Справочник.Номенклатура]
   |, ParentId ParentId, Id Id, Уровень, Сортировка Наименование, Code Код
   |, Себестоимость Себестоимость
   |, Количество Количество
   |, ПроданоНаСумму ПроданоНаСумму
   //|Into "+ТаблицаГрупп+"
   |From "+ТаблицаГрупп+" ИмяТаблицы (NoLock)
   |";

   ТЗ=СоздатьОбъект("ТаблицаЗначений");
   Попытка
       РадугаЗапрос.ВыполнитьИнструкцию(ТекстЗапроса,ТЗ);          
   Исключение
       Предупреждение("Произошла ошибка при выполнении запроса (Создание таблицы )!!!");
       Текст=СоздатьОбъект("Текст");
       Текст.ДобавитьСтроку(ТекстЗапроса);
       Текст.Показать("12");
       Сообщить(ОписаниеОшибки());
       Возврат "";
   КонецПопытки;
   ПечатьТЗ(ТЗ);    
   Возврат "";
КонецФункции    // СортировкаРезультатовЗапросаПоИерархии
14 vde69
 
26.09.12
09:15
(12) если есть транзакция (в том числе скрытая, например проведение документа) и из транзакции вызываешь свои апдейты то все запросы к серверу вызываемые внутри этой транзакции будут "грязными" то есть видеть результат твоих апдейтов.

грязный - это запрос который видет результат незавершенной транзакции,
чистый - это запрос который видит состояние бех движений текущей транзакции

в 1с ВСЕ запросы грязные
15 Андрей_Андреич
 
naïve
26.09.12
09:22
(14) тупой отчет. режим сейчас монопольный все окна закрыты. или я не про то?
16 vde69
 
26.09.12
09:25
(15) ты в отчете делаешь апдейт??? ну ты и индеец!!!

моя логика была такая

1. ты делешь несколько апдейтов,
2. значит ты обязан делать это в транзакции, иначе ты рискуешь сделать только часть адейтов
3. если есть транзакция - чтение грязное

а теперь покажи где я ошибся
17 Андрей_Андреич
 
naïve
26.09.12
09:46
(16) "ну ты и индеец!!!" - да хоть евреец :)
Я в отчете собрал прямым запросом в таблиицу данные о продажах.
Теперь мне надо построить иерархию по группам. Я дернул вошедшие в запрос группы (Id ParentId Descr) из номенклатурника во временную таблицу. Естественно, я могу апдейтить ее хоть 100 раз. Я понимаю, что дурак. Но не понимаю, почему.
18 ADirks
 
26.09.12
11:16
а ты диагностику от SQL выведи, глядишь и понятно станет чё за фигня

РадугаЗапрос.Отладка(1);
РадугаЗапрос.ВыполнитьИнструкцию(ТекстЗапроса,ТЗ);

и без попытки

+ не Сообщить(ОписаниеОшибки());  а Сообщить(РадугаЗапрос.ПолучитьОписаниеОшибки());
19 ADirks
 
26.09.12
11:20
там у тебя синтаксические ошибки, а ты и не видишь. Навскидку

   |Update "+ТаблицаГрупп+"
   |Set
   |Уровень = 0
   |,Сортировка = Номенклатура.Descr, Code = Номенклатура.Code
   |From "+ТаблицаГрупп+" ТаблицаГрупп (NoLock)

2 ошибки: (NoLock) в update - нонсенс; алиас для updatable table - нельзя
20 Андрей_Андреич
 
naïve
26.09.12
11:21
(18) ошибок не выдает
21 Ёпрст
 
гуру
26.09.12
11:29
(19)
алиас для updatable table - нельзя

?
Еще как можно!
http://msdn.microsoft.com/ru-ru/library/ms177523.aspx
22 Андрей_Андреич
 
naïve
26.09.12
11:37
(21)Как? Имя, сестра - имя! Я уже через копию сделал, как и в прошлый раз. Некрасиво.
23 Ёпрст
 
гуру
26.09.12
11:39
(22) всмысле как ?
алияс для апдейт можно писать..
24 Андрей_Андреич
 
naïve
26.09.12
11:43
(23) Вот я и пишу, раз уж разрешили. Не ругается и не апдейтит.
25 ADirks
 
26.09.12
11:44
(21) прикольно... и правда можно
а я с чего-то думал, что нет
26 Андрей_Андреич
 
naïve
26.09.12
11:45
(25) Вот давай вместе и освоим :)
27 Ёпрст
 
гуру
26.09.12
11:46
(24) а так ?

 |Update Табличка
 |Set
 |Табличка.Уровень = 0
 |,Табличка.Сортировка = Номенклатура.Descr, Табличка.Code = Номенклатура.Code
 |From "+ТаблицаГрупп+" Табличка
 | inner .... left что там у тя дальше по тексту ?
28 Ёпрст
 
гуру
26.09.12
11:48
так работает ?

   |Update Табличка
   |Set
   |Табличка.Сортировка = Rtrim(ДопТаблица.Сортировка)+RTrim(ТаблицаГрупп.Сортировка)
   |From "+ТаблицаГрупп+" Табличка
   |Left Join "+ТаблицаГрупп+" ДопТаблица (NoLock) On Табличка.ParentId = ДопТаблица.Id
   |Where Табличка.Уровень=0
29 Андрей_Андреич
 
naïve
26.09.12
11:51
(28) Нет
30 Андрей_Андреич
 
naïve
26.09.12
12:02
(28) Что-то результат изменился, но чего-то я недоучел. Ща покопаемся.
31 Андрей_Андреич
 
naïve
26.09.12
12:09
Ура! Заработало! Спасибо Ёпрст - я бы свой мозг так не вывихнул. Итоговый текст:
   |Update "+ТаблицаГрупп+"
   |Set Уровень=1
   |, Сортировка=LTrim(Str(1))+RTrim(Сортировка)
   |From "+ТаблицаГрупп+" Where ParentId = '     0   '
   |
   |Set @MaxLevel=1
   |
   |While 1=1 Begin
   |Update ТаблицаГрупп
   |Set ТаблицаГрупп.Уровень=@MaxLevel+1,
   |ТаблицаГрупп.Сортировка = Rtrim(ДопТаблица.Сортировка)+LTrim(Str(@MaxLevel+1))+RTrim(ТаблицаГрупп.Сортировка)
   |From "+ТаблицаГрупп+" ТаблицаГрупп
   |Inner Join "+ТаблицаГрупп+" ДопТаблица On ТаблицаГрупп.ParentId = ДопТаблица.Id
   |Where ТаблицаГрупп.Уровень=0 And ДопТаблица.Уровень=@MaxLevel
   |    If @@RowCount=0 Begin
   |        Break
   |    END
   |    Set @MaxLevel=@MaxLevel+1
   |END
32 Андрей_Андреич
 
naïve
26.09.12
12:11
(28) Оптимизировать это можно / нужно?
33 Ёпрст
 
гуру
26.09.12
12:22
(32) дык если работает.. то и забить
:)
34 Андрей_Андреич
 
naïve
26.09.12
12:24
(33) Так это готовая сортировка справочника по иерахии - я ее во все отчеты вставлять буду.
35 ADirks
 
27.09.12
06:46
(34) Тогда подумай лучше вот куда: навесить триггеры на insert/update/delete нужных справочников, чтобы эти твои таблички поддерживать в актуальном состоянии. На каждый справочник своя табличка естественно.
Ещё почитай  http://www.1cpp.ru/forum/YaBB.pl?num=1153469047  там правда речь про фильтры, но принцип примерно такой же.
36 Андрей_Андреич
 
naïve
27.09.12
07:04
(35) Это мне придется на каждый справочник + при создании новых. А тут универсальное, хотя и менее эффективное решение.
Ну и напоследок пожалуюсь. Эта долбаная 1С со своей восьмеркой вдалбливает всем в бошки, что 7.7 умерла и не стоит с ней возиться, а уж развивать тем более. Вот и стараюсь все по минимуму делать.
37 ADirks
 
27.09.12
07:19
(36) Ну так ты же не ручками это делать будешь, а например так:


//ТБазаДанных::
Функция ПроверитьОбъектыSQLСервера()
   ...
   
   Для н = 1 По Метаданные.Справочник() Цикл
       МетаСпр = Метаданные.Справочник(н);
       Состояние("Представление: "+МетаСпр);
       Если СоздатьПредставление_Справочник(МетаСпр) = 0 Тогда
           фОшибокНет = 0;
       КонецЕсли;
       Если МетаСпр.КоличествоУровней > 1 Тогда
           Если ТриггерДляИерархии(МетаСпр) = 0 Тогда
               Возврат 0;
           КонецЕсли;
       КонецЕсли;
   КонецЦикла;
   
   ...
   
   Возврат 1;
КонецФункции



Процедура ПриНачалеРаботыСистемы()
   ВремяПоследнейЗаписи = "";
   ФС.АтрибутыФайла(КаталогИБ() + "1cv7.md",,,,, ВремяПоследнейЗаписи);
   Если ВремяПоследнейЗаписи <> СокрЛП(Константа.ПоследнееИзменениеКонфигурации) Тогда
       Если МонопольныйРежим() = 1 Тогда
           оБазаДанных = СоздатьОбъект("ТБазаДанных");
           Если оБазаДанных.ПроверитьОбъектыSQLСервера() <> 1 Тогда
               Возврат 0;
           КонецЕсли;
           ФС.ПереименоватьФайл(КаталогИБ()+"TurboMd.prm", КаталогИБ()+"TurboMd.prm~", 1);
           
           Константа.ПоследнееИзменениеКонфигурации = ВремяПоследнейЗаписи;
       ИначеЕсли глФлагОтладки = 1 Тогда
           Сообщить("Внимание! Время последнего изменения файла конфигурации отличается от записанного в константу!", "!");
       Иначе
           Предупреждение(
           "Для корректной работы необходим
           |однократный монопольный вход в систему!
           |Сообщите об этом администратору!", 15);
           Возврат 0;
       КонецЕсли;
   КонецЕсли;
КонецПроцедуры
38 Андрей_Андреич
 
naïve
27.09.12
07:33
(37) Я же до гуру все равно не дорасту. Моему мозгу и то, что сделал, с трудом дается. К тому же функция заодно после причесывания итоги по группам будет собирать. В общем, я себе комфортную приблуду для отчетиков сделаю и ладушки.
Мне структурное программирование с детства вбили и Ваши ООП туда плохо укладываются.
И еще раз огромное спасибо всем участвовавшим в обсуждении.
39 Mikeware
 
27.09.12
07:40
(38)Собственно, это не ООП, а именно подход структурного программирования...
40 ADirks
 
27.09.12
08:28
(38) До гур доростать и не надо. Но расти - обязательно.

Собирать итоги - это кагбе дело собственно отчёта, вспомогательные же таблицы нужны для облегчения этого дела. Т.е. нужен некий баланс затрат: на формирование статических вспомогательных данных и на рассчет оперативных данных. Представь, у тебя с десяток пользователей одновременно запустят отчёты, которые начнут собирать итоги по всем группам, не особо разбирая надо-ненадо, и пихать в таблички к тому же. И всё это будет использовано лишь однократно.
А для удобства понапиши лучше процедур для генерации текста запроса - будет гораздо полезней.

про ООП уже сказали :)
41 Андрей_Андреич
 
naïve
27.09.12
08:33
(40) я дико извиняюсь - но если пользователь задал отчет - наверное оно ему надо.
А итоги по группам все равно собирать. Не по всем, а только вошедшим в запрос. Ну и пусть скуль одним запросом 2 дела делает - собирает все группы и итоги по ним. Что-то я тебя не понял.
42 Mikeware
 
27.09.12
08:36
+(40)"плох тот чайник, который не стремится стать самоваром"©
43 ADirks
 
27.09.12
08:42
(41) Не надо писать в таблички однократно используемые данные - это лишняя нагрузка на систему. Многократно же используемые данные надо поддерживать в актуальном состоянии, а не рассчитывать каждый раз.
44 Андрей_Андреич
 
naïve
27.09.12
08:53
(43) совершенно согласен, но вот цена вопроса... мне кажется - это и так уже копеечные затраты. Столь глубокой оптимизации мне не надо - на моих объемах все и так летает.
И, этаа... Не бейте меня, а? Ну тоже ведь каждый байтик не вылизываете?
45 Mikeware
 
27.09.12
09:01
(44) на массовых операциях - иногда приходится и вылизывать...
46 Mikeware
 
27.09.12
09:02
+(45) иногда лучше сразу делать правильно...
AdBlock убивает бесплатный контент. 1Сергей