Имя: Пароль:
1C
 
Как сравнить две версии регистра сведений
0 Гений 1С
 
гуру
09.01.07
18:33
Короче, нужно отследить изменения в регистре сведений.
Итак, есть в одной таблице значений колонки:
Изм1, Изм2,...ИзмН   Рес1, ...РесМ
Это начальное состояние регистра сведений.

В другой таблице значений такие же колонки:
Изм1, Изм2,...ИзмН   Рес1, ...РесМ
Это конечное состояние регистра сведений.

Нужно получить результирующую таблицу:
Изм1, Изм2,...ИзмН   Рес1, ...РесМ Статус
Где Статус:
0  - запись не изменилась
1  - запись изменилась
-1 - запись удалилась
2  - были изменены ресурсы (желательно еще и список этих ресурсов)

Кто такое делал, как подступить?
1 Terv
 
09.01.07
18:35
чем свернуть не подходит?
2 Гений 1С
 
гуру
09.01.07
18:35
(1) ресурсы не числовые
3 Варвар
 
09.01.07
18:41
"Вывести список", и "сравнить файлы" в 1С не катит?
4 Гений 1С
 
гуру
09.01.07
18:49
(3) Не ручками, а программно и регулярно.. ;-) Не катят...
5 Johnbay
 
09.01.07
18:58
Запросом самое простое думаю
6 jcage
 
09.01.07
19:02
8.1 или 8.0?
7 Johnbay
 
09.01.07
19:04
ВЫБРАТЬ
   КурсыВалют.Курс,
   КурсыВалют.Кратность,
   КурсыВалют.Период,
   КурсыВалют1.Валюта,
   КурсыВалют1.Курс КАК Курс1,
   КурсыВалют1.Кратность КАК Кратность1,
   ВЫБОР
       КОГДА (НЕ КурсыВалют.Курс = КурсыВалют1.Курс)
               ИЛИ (НЕ КурсыВалют.Кратность = КурсыВалют1.Кратность)
           ТОГДА "2"
   КОНЕЦ КАК Статус
ИЗ
   РегистрСведений.КурсыВалют КАК КурсыВалют
       ПОЛНОЕ СОЕДИНЕНИЕ РегистрСведений.КурсыВалют КАК КурсыВалют1
       ПО КурсыВалют.Валюта = КурсыВалют1.Валюта
8 Johnbay
 
09.01.07
19:04
Остальные статусы пропиши и все дела
9 jcage
 
09.01.07
19:05
(7) не хочу обидеть коллега, но мне кажется, что вы написали фигню.
10 Johnbay
 
09.01.07
19:06
ну вместо
ПОЛНОЕ СОЕДИНЕНИЕ РегистрСведений.КурсыВалют КАК КурсыВалют1
       ПО КурсыВалют.Валюта = КурсыВалют1.Валюта

нада поправить на
ПОЛНОЕ СОЕДИНЕНИЕ РегистрСведений.КурсыВалют1 КАК КурсыВалют1
       ПО КурсыВалют.Валюта = КурсыВалют1.Валюта

т.е. второй регистр "КурсыВалют1"
в итоге
ВЫБРАТЬ
   КурсыВалют.Курс,
   КурсыВалют.Кратность,
   КурсыВалют.Период,
   КурсыВалют1.Валюта,
   КурсыВалют1.Курс КАК Курс1,
   КурсыВалют1.Кратность КАК Кратность1,
   ВЫБОР
       КОГДА (НЕ КурсыВалют.Курс = КурсыВалют1.Курс)
               ИЛИ (НЕ КурсыВалют.Кратность = КурсыВалют1.Кратность)
           ТОГДА "2"
   КОНЕЦ КАК Статус
ИЗ
   РегистрСведений.КурсыВалют КАК КурсыВалют
       ПОЛНОЕ СОЕДИНЕНИЕ РегистрСведений.КурсыВалют1 КАК КурсыВалют1
       ПО КурсыВалют.Валюта = КурсыВалют1.Валюта
11 Гений 1С
 
гуру
09.01.07
19:07
Запрос не катит, вторая ТЗ формируется не из регистра... а лишь по сути имитирует регистр.
12 jcage
 
09.01.07
19:09
(0) Тебе похоже просто надо сравнить две ТЗ.
Сортируй по периодам и валютам, далее обходи первую ТЗ и построчно сравнивай.
13 Гений 1С
 
гуру
09.01.07
19:09
(12) у меня 4 регистра, надо какую-то универсальную хрень, хотя подход неплохой.
14 Johnbay
 
09.01.07
19:09
(11)
если все статично (формирующаяся ТЗ_2) то можно и нарисовать этот регистр, сгружать туда данные, строить запрос, удалять.
15 jcage
 
09.01.07
19:14
(14) Я как-то пробовал использовать регистр сведений как буфер - фигня получилась. Запись в регистр - очень долгая операция по сравнению с работой с ТЗ.
(13) Так там написать универсальную процедуру легко. Просто получаешь первую строку из первой ТЗ, получаешь первую строку из второй ТЗ и сравниваешь. Тут важно замечательное свойство регистра сведений - уникальность записи по комбинации измерений (и периоду). Т.е. если ты осортируешь ТЗ по периоду и всем измерениям - то можешь со 100 % сравнить. Правда сортировка может времени дофига занять. Но зато обход будет только один.
16 Johnbay
 
09.01.07
19:17
(15)
Смотря как писать. По одной записи - да, долго. Оптом - быстрее напорядок :)
Ну в общем хозяин - барин.
17 asady
 
09.01.07
19:20
(0) попробуй в транзакции попытку записи в РС

если будет ошибка - уникальный набор измерений уже есть - найти его легко.

если ошибки нет - такого набора нет - искать нечего.
18 Neco
 
09.01.07
20:50
Как вариант выгрузить ТЗ1 и ТЗ2 в ТЗ. Далее свернуть ТЗ по измерениям и.. ресурсам. Потом, с помощью НайтиСтроки(..) найти все строки с Изм1, Изм2,...ИзмН  и проверить, если строк > 1, то ресурсы менялись. Далее можно пройтись по ресурсам и по сравнивать их и выявить какой ресурс менялся.
19 Гений 1С
 
гуру
10.01.07
12:12
(18) Я придумал другой способ.
Вот примерный код, пока еще не проверял, но думаю понятен ход мысли (нужно еще дебуггить):
//ТЗИсх - какая таблица была
//ТЗКон - какая таблица стала
//Названия колонок должны совпадать
//Ключи - массив ключей
Функция обСравнитьПоКлючамТЗ(ТЗНач, ТЗКон, Ключи, НазваниеКолонкиРезультата="Статус")
   ТЗРез=Новый ТаблицаЗначений();
   КолРез=Новый Массив();
   
   //Ищем общие колонки в обоих таблицах
   Для Каждого Эл ИЗ ТЗНач.Колонки Цикл
       Если ТЗКон.Колонки.Найти(Эл.Имя)<>Неопределено Тогда
           КолРез.Добавить(Эл.Имя);
       КонецЕсли;
   КонецЦикла;
   
   //Добавляем эти колонки в таблицу-результат
   Для Каждого Эл ИЗ КолРез Цикл
       ТЗРез.Колонки.Добавить(Эл);
   КонецЦикла;
   
   //Добавляем служебные колонки
   ТЗРез.Колонки.Добавить("___ТЗНачИндекс");
   ТЗРез.Колонки.Добавить("___ТЗКонИндекс");
   ТЗРез.Колонки.Добавить("___ТЗНачКонтроль");
   ТЗРез.Колонки.Добавить("___ТЗКонКонтроль");
   
   
   Для Каждого Стр Из ТЗНач Цикл
       НовСтр=ТЗРез.Добавить();
       НовСтр.___ТЗНачИндекс=ТЗНач.Индекс(Стр);
       НовСтр.___ТЗКонИндекс=0;
       Для Каждого Эл Из Ключи Цикл
           НовСтр[Эл]=Стр[Эл];
       КонецЦикла;
   КонецЦикла;
   
   Для Каждого Стр Из ТЗКон Цикл
       НовСтр=ТЗРез.Добавить();
       НовСтр.___ТЗНачИндекс=0;
       НовСтр.___ТЗКонИндекс=ТЗКон.Индекс(Стр);
       Для Каждого Эл Из Ключи Цикл
           НовСтр[Эл]=Стр[Эл];
       КонецЦикла;
   КонецЦикла;
   
   ТЗРез.ЗаполнитьЗначения(1, "___ТЗНачКонтроль");
   ТЗРез.ЗаполнитьЗначения(1, "___ТЗКонКонтроль");
   
   
   СтрокаСвертки="";
   Для Каждого Эл Из Ключи Цикл
       СтрокаСвертки=СтрокаСвертки+?(СтрокаСвертки="","",",")+Эл;
   КонецЦикла;
   
   СтрокаИтогов="";
   Для Каждого Эл Из КолРез Цикл
       СтрокаИтогов=СтрокаИтогов+?(СтрокаИтогов="","",",")+Эл;
   КонецЦикла;
   
   //Сворачиваем
   ТЗРез.Свернуть(СтрокаСвертки, СтрокаИтогов);
   
   //Восстанавливаем общие колонки
   ЗнКол=Новый Массив();
   Для Каждого Эл ИЗ КолРез Цикл
       Если ТЗРез.Колонки.Найти(Эл)=Неопределено Тогда
           ТЗРез.Колонки.Добавить(Эл);
           ЗнКол.Добавить(Эл);
       КонецЕсли;
   КонецЦикла;
   
   ТЗРез.Колонки.Добавить(НазваниеКолонкиРезультата);
   
   //Формируем таблицу результата
   Для Каждого Стр ИЗ ТЗРез Цикл
       Если Стр.___ТЗНачИндекс=0 Тогда
           Стр[НазваниеКолонкиРезультата]=+1; //Добавлена
           Для Каждого Эл ИЗ ЗнКол Цикл
               Зн=ТЗКон.___ТЗКонИндекс[Эл];
               Стр[Эл]=Зн;
           КонецЦикла;
       ИначеЕсли Стр.___ТЗКонИндекс=0 Тогда
           Стр[НазваниеКолонкиРезультата]=-1; //Удалена
           Для Каждого Эл ИЗ ЗнКол Цикл
               Зн=ТЗНач.___ТЗНачИндекс[Эл];
               Стр[Эл]=Зн;
           КонецЦикла;
       Иначе
           Р=Новый Структура();
           Для Каждого Эл ИЗ ЗнКол Цикл
               ЗнНач=ТЗНач.___ТЗНачИндекс[Эл];
               ЗнКон=ТЗКон.___ТЗКонИндекс[Эл];
               Если ЗнНач<>ЗнКон Тогда
                   Р.Вставить(Эл, ЗнНач);
               КонецЕсли;
               Стр[Эл]=ЗнКон;
           КонецЦикла;
           Стр[НазваниеКолонкиРезультата]=Р; //Структура изменений
       КонецЕсли;
   КонецЦикла;
   Возврат ТЗРез;
КонецФункции
20 Гений 1С
 
гуру
10.01.07
14:00
Вот окончательная отлаженная версия, юзается метод Свернуть:

//ТЗИсх - какая таблица была
//ТЗКон - какая таблица стала
//Названия колонок должны совпадать
//Ключи - массив ключей
Функция обСравнитьПоКлючамТЗ(ТЗНач, ТЗКон, Ключи, НазваниеКолонкиРезультата="Статус")
   ТЗРез=Новый ТаблицаЗначений();
   КолРез=Новый Массив();
   
   //Ищем общие колонки в обоих таблицах
   Для Каждого Эл ИЗ ТЗНач.Колонки Цикл
       Если ТЗКон.Колонки.Найти(Эл.Имя)<>Неопределено Тогда
           КолРез.Добавить(Эл.Имя);
       КонецЕсли;
   КонецЦикла;
   
   //Добавляем эти колонки в таблицу-результат
   Для Каждого Эл ИЗ КолРез Цикл
       ТЗРез.Колонки.Добавить(Эл);
   КонецЦикла;
   
   //Добавляем служебные колонки
   ТЗРез.Колонки.Добавить("___ТЗНачИндекс");
   ТЗРез.Колонки.Добавить("___ТЗКонИндекс");
   ТЗРез.Колонки.Добавить("___ТЗНачКонтроль");
   ТЗРез.Колонки.Добавить("___ТЗКонКонтроль");
   
   
   Для Каждого Стр Из ТЗНач Цикл
       НовСтр=ТЗРез.Добавить();
       НовСтр.___ТЗНачИндекс=ТЗНач.Индекс(Стр)+1;
       НовСтр.___ТЗКонИндекс=0;
       Для Каждого Эл Из Ключи Цикл
           НовСтр[Эл]=Стр[Эл];
       КонецЦикла;
   КонецЦикла;
   
   Для Каждого Стр Из ТЗКон Цикл
       НовСтр=ТЗРез.Добавить();
       НовСтр.___ТЗНачИндекс=0;
       НовСтр.___ТЗКонИндекс=ТЗКон.Индекс(Стр)+1;
       Для Каждого Эл Из Ключи Цикл
           НовСтр[Эл]=Стр[Эл];
       КонецЦикла;
   КонецЦикла;
   
   ТЗРез.ЗаполнитьЗначения(1, "___ТЗНачКонтроль");
   ТЗРез.ЗаполнитьЗначения(1, "___ТЗКонКонтроль");
   
   
   СтрокаСвертки="";
   Для Каждого Эл Из Ключи Цикл
       СтрокаСвертки=СтрокаСвертки+?(СтрокаСвертки="","",",")+Эл;
   КонецЦикла;
   
   СтрокаИтогов="___ТЗНачИндекс,___ТЗКонИндекс,___ТЗНачКонтроль,___ТЗКонКонтроль";
   
   //Сворачиваем
   ТЗРез.Свернуть(СтрокаСвертки, СтрокаИтогов);
   
   //Восстанавливаем общие колонки
   ЗнКол=Новый Массив();
   Для Каждого Эл ИЗ КолРез Цикл
       Если ТЗРез.Колонки.Найти(Эл)=Неопределено Тогда
           ТЗРез.Колонки.Добавить(Эл);
           ЗнКол.Добавить(Эл);
       КонецЕсли;
   КонецЦикла;
   
   ТЗРез.Колонки.Добавить(НазваниеКолонкиРезультата);
   
   //Формируем таблицу результата
   Для Каждого Стр ИЗ ТЗРез Цикл
       Если Стр.___ТЗНачКонтроль>1 ИЛИ Стр.___ТЗКонКонтроль>1 Тогда
           Возврат Новый Структура("КодОшибки","ДублированиеКлюча");
       ИначеЕсли Стр.___ТЗНачИндекс=0 Тогда
           Стр[НазваниеКолонкиРезультата]=+1; //Добавлена
           Для Каждого Эл ИЗ ЗнКол Цикл
               Зн=ТЗКон.Получить(Стр.___ТЗКонИндекс-1)[Эл];
               Стр[Эл]=Зн;
           КонецЦикла;
       ИначеЕсли Стр.___ТЗКонИндекс=0 Тогда
           Стр[НазваниеКолонкиРезультата]=-1; //Удалена
           Для Каждого Эл ИЗ ЗнКол Цикл
               Зн=ТЗНач.Получить(Стр.___ТЗНачИндекс-1)[Эл];
               Стр[Эл]=Зн;
           КонецЦикла;
       Иначе
           Р=Новый Структура();
           Для Каждого Эл ИЗ ЗнКол Цикл
               ЗнНач=ТЗНач.Получить(Стр.___ТЗНачИндекс-1)[Эл];
               ЗнКон=ТЗКон.Получить(Стр.___ТЗКонИндекс-1)[Эл];
               Если ЗнНач<>ЗнКон Тогда
                   Р.Вставить(Эл, ЗнНач);
               КонецЕсли;
               Стр[Эл]=ЗнКон;
           КонецЦикла;
           Стр[НазваниеКолонкиРезультата]=Р; //Структура изменений
       КонецЕсли;
   КонецЦикла;
   Возврат ТЗРез;
КонецФункции
21 Гений 1С
 
гуру
10.01.07
16:29
22 vde69
 
10.01.07
16:45
23 kiruha
 
10.01.07
16:54
(20) А про проблему больших ТЗ в 8.0 не слышал?
И время на больших данных измерял?
24 simol
 
10.01.07
17:04
А если это использовать перед записью движений регистра, то вроде как если при отсутсвии изменений можно не записывать:
1. Поидее выиграш в скорости
2. Не изменяются последовательности.

Как такая идея?
25 Гений 1С
 
гуру
10.01.07
19:16
(23) У меня данные не большие, но в основном здесь работает метод свернуть, а как его ускорить, мы знаем. Книга знаний: v8: Ускорение типовой свертки таблиц значений в 1С80

(22) да, я такой метод знаю и его рассматривал, но по-моему СВЕРТКА быстрее, чем СОРТИРОВКА, да еще и построение индекса, нафиг... ;-)
26 Гений 1С
 
гуру
10.01.07
19:16
(22) вставил кросс линки между моей и этой статьей.
27 Гений 1С
 
гуру
10.01.07
19:16
у меня готовая функция универсальная, а в (22) еще дописывать надо.