Имя: Пароль:
1C
1C 7.7
v7: Оптимизация генерации короткого кода с заполнением пропущенных кодов
0 brenli
 
03.09.19
09:28
Всем добра.
Есть база с большим количеством номенклатуры, кто то писал механизм генерации короткого 5 значного кода, но проблема в том что справочник очень большой и новый код генерируется больше 5 минут.

Текущий алгоритм формирования мягко сказать не особо производительный

    Пока 1=1 Цикл
        Если СпрНом.НайтиПоРеквизиту("НомКод",НовыйНомер,1)=1 Тогда
            Если ФлагСпецГруппы=1 Тогда
                ПредНомер         = ПредНомер+1;
                НовыйНомер         = ПредНомер + 1;
                ДлнНовыйНомер     = СтрДлина(НовыйНомер);
                НовыйНомер         = Лев("М00000000",9-ДлнНовыйНомер)+НовыйНомер;
            Иначе
                ПредНомер         = Число(ПредНомер) + 1;
                НовыйНомер         = СокрЛП(Строка(Число(ПредНомер) + 1));
                ДлнНовыйНомер     = СтрДлина(НовыйНомер);
                НовыйНомер         = Лев("00000",5-ДлнНовыйНомер)+НовыйНомер;
            КонецЕсли;
        Иначе
            Сообщить("Новый код: "+НовыйНомер);
            Прервать;
        КонецЕсли;
    КонецЦикла;

Так же в базе существует много промежутков . Например 00022 - 00025  еще 2 номера не использованы.
Были мысли создать еще справочник в котором хранить диапазоны пустых значений. При записи номенклатуры брать оттуда значения и тут же его удалять. Если справочник диапазонов пустой - брать последний номер номенклатуры + 1.
Как бы вы оптимизировали данный процесс?
1 d4rkmesa
 
03.09.19
09:34
(0) С помощью прямого запроса получить МаксимальныйНомер, как обычно в 8-ке делают. На промежутки забить.
2 Дегенератор идей
 
03.09.19
09:35
я бы завел две константы.. присвоил каждой максимальный код из существующих.
новый номер брал из константы и увеличивал на один.
новый номер потом записывал в константу
3 АгентБезопасной Нацио
 
03.09.19
09:36
посчитай прямым запросом...
способы генерации таблицы с числами "от и до" есть на инфостарте
затем правое соединение, и иснулл
4 АгентБезопасной Нацио
 
03.09.19
09:36
(1) максимальный номер у него и так считает платформа
5 Дегенератор идей
 
03.09.19
10:07
(4) нет.. там две последовательности кодов
6 GreyK
 
03.09.19
10:15
(0) Примерно так:
//*******************************************
Функция ПолучитьНовыйКод(Префикс="")
    СтрДлинаКода = 9 - СтрДлина(Префикс);
    МаксКод = Число(Лев("999999999",СтрДлинаКода));
    СпрНом = СоздатьОбъект("Справочник.Номенклатура");
    СчетчикЦикла = 0;
    Для СчетчикЦикла = 1 По МаксКод Цикл
        НовыйКод = Формат(СчетчикЦикла,"Ч(0)"+СтрДлинаКода);
        Если СпрНом.НайтиПоКоду(Префикс+НовыйКод,0) = 0 Тогда
            Сообщить("Новый код: "+Префикс+НовыйКод);
        КонецЕсли;
    КонецЦикла;
КонецФункции;
7 Карст
 
03.09.19
10:36
извращенство какое то
8 GreyK
 
03.09.19
10:42
(7) Есть более правильный путь один раз сделать перенумерацию существующих элементов справочника, но видимо кому то хочется растянуть "удовольствие" :)
9 Дегенератор идей
 
03.09.19
10:49
(8) перенумерацию можно делать если код не используется для обменов и прочего..
очень смелое решение взять и сделать перенумерацию не зная подробностей)))))))
10 GreyK
 
03.09.19
11:02
(9) Очень смелое решение использовать код для идентификации в обменах :)
11 Злопчинский
 
03.09.19
11:09
забить на пропуски.
код это вообще просто ид некий (да и то нестабильный). требовать от Ида последовательности - имхо как-то излишне.
.
12 GreyK
 
03.09.19
11:25
(11) И что делать пользователям, про прямоту их рук говорить не будем, если у них новый код выходит "9", "99", "999", "9999" и пр.?
13 Карст
 
03.09.19
11:34
(12) разрядность , длину низя что ле увеличить ?
14 brenli
 
03.09.19
11:36
(8) Там сеть магазов используют этот код для поиска.
Завопят все и в один голос если перенумеровать.
15 HawkEye
 
03.09.19
11:36
(0) выкинуть код из (0), научиться использовать префиксы и не забивать себе голову ерундой про промежутки...
16 Злопчинский
 
03.09.19
11:39
(12) застрелиться ;-)
если код юзается для синхронизации - то раньше надо было думать чтобы обеспечить достаточный диапазон для значений. самое первое тривиальное действие - запретить изменение кода вручную. а так - ССЗБ.
17 brenli
 
03.09.19
11:40
(15) Префиксы используются в основном коде.
А это так сказать короткий
18 brenli
 
03.09.19
11:41
(16) Для синхронизации он не используется.

По нему просто быстро ищут товар
19 GreyK
 
03.09.19
11:41
(13) А чем разрядность поможет? Код "999" пользователь может вбить и при 9ти-значной разрядности.
20 brenli
 
03.09.19
11:45
(19) Код основной идет с префиксом
И вводить их неудобно
21 brenli
 
03.09.19
11:45
Так давно у них
22 Злопчинский
 
03.09.19
11:46
(18) уроды, ССЗБ.
текущие коды перенести в АРТИКУЛ.
перенумеровать и не трахать себе мозг.
23 GreyK
 
03.09.19
11:47
(21) Функцию из (6) попробовал?
24 HawkEye
 
03.09.19
11:47
(17) зачем номенклатуре ДВА уникальных идентификатора? ))
25 brenli
 
03.09.19
11:49
(23) Нет еще. Не на месте.
26 brenli
 
03.09.19
11:50
(24) Не я это придумал. ХЗ зачем.
Говорю же ...подбор делают по коротким кодам
27 HawkEye
 
03.09.19
11:52
(26) так перед тем, как что-то исправлять, надо понять
- ЗАЧЕМ это сделано?
- ПОЧЕМУ это сделано именно так?

и только получив ответы на эти вопросы, мчаться с шашкой наголо
28 brenli
 
03.09.19
11:54
(27) Согласитесь . Легче ввести 00025 или 683222 . Чем PS0000082, KT0000121 и т.д
29 АгентБезопасной Нацио
 
03.09.19
11:54
(27) ну так он и не хочет "исправлять", он пытается решить локальную проблему "быстрое получение свободного кода".
30 brenli
 
03.09.19
11:56
(29) Просто если запустить им все и перенумеровать глобально они не будут находить товар. Начнется ахтунг.
У них на ценниках эти коды распечатываются. Начнется дичайший пересорт
31 brenli
 
03.09.19
11:57
Меня съедят просто
32 HawkEye
 
03.09.19
11:57
(29) пф.... это непрофессиональный подход
33 АгентБезопасной Нацио
 
03.09.19
12:20
(28)
- Петька, прибор !?!?!???
-- Двадцать!
- чо "двадцать"??
-- а чо "прибор"?
©
иногда легче знать "код в группе".
но все зависит от процессов...

(32) профессиональный подход - это устранить затык (чтоб не вставала текущая работа в текущем виде), а затем "делать правильно".
34 vova1122
 
03.09.19
12:38
(0) Интересно сколько всего номенклатуры в справочнике, что только первый пустой номер ищется целых 5 минут
35 Rema Dan
 
03.09.19
12:47
(0) Если стоит задача найти пропуски кодов и кода исключительно цифровые, то можно выбрать все кода в отсортированную коллекцию значений и искать пропуски бинарным поиском (сравнивая код "по порядку" и код "по факту").
36 VladZ
 
03.09.19
12:51
(0) "генерации короткого кода с заполнением пропущенных кодов" - работа ради работы? Зачем это нужно?
37 HawkEye
 
03.09.19
12:59
(28) а кто с этим спорит? просто зачем тогда тебе длинный код, если его никто не использует и короткий является уникальным?

(33) это софистика... у него и сейчас все работает, по крайней мере в (0) обратного не утверждается.
38 Лефмихалыч
 
03.09.19
13:00
лень читать.
индексировать НомКод предлагали же уже?
39 HawkEye
 
03.09.19
13:01
(38) неа.. ты первый
40 brenli
 
03.09.19
13:05
(34) 50 000
41 HawkEye
 
03.09.19
13:08
(40) поставь фузион из соседний ветки и забудь )))
42 Rema Dan
 
03.09.19
13:28
(40) Выбираешь все 50 000 кодов в отсортированную колекцию значений и смотришь какой код у элемента под номером 25000. Если он больше 25000, значит в промежутке кодов 1-2500 есть пропуск, если меньше, то пропуск в промежутке 25001-50000. Повторять нарезку пополам, пока не найдёшь пропуск.
43 brenli
 
03.09.19
13:44
(42) Типа бинарный поиск?
44 Rema Dan
 
03.09.19
13:47
(43) Типа его. Всяко лучше чем сыпать запросами на проверку каждого кода в справочнике.
45 Salimbek
 
03.09.19
14:01
(42) Не пойдет, у автора могут быть и какие-то ФлагСпецГруппы
(0) select min(Spr.Code) from $Справочник.Номенклатура as Spr left join $Справочник.Номенклатура as Spr1 on Spr.Code=Spr1.Code+1 where Spr1.Code Is Null
46 brenli
 
03.09.19
14:38
(45) Идеи крутые.
С запросом интересно. Вот только поле то строковое, а в запросе + 1 . Вероятно будет конкатенация.
47 brenli
 
03.09.19
14:41
(45) Флаг СпецГруппы это отдельный диапазон кодов с префиксом М и он 9 значный. Нас интересует все остальное что не входит в  спецгруппу.
48 Salimbek
 
03.09.19
15:03
(46) Х.з. с чем вы там балуетесь, если dbf и 1sqlite, то
select cast(spr.code as int) as Code into #tmp from Справочник_Номенклатура as spr; //<-- тут можно через substr отрезать лидирующие префиксы
select min(Spr.Code) from #tmp as Spr left join #tmp as Spr1 on Spr.Code=Spr1.Code+1 where Spr1.Code Is Null
49 brenli
 
04.09.19
14:29
Пишу прямой запрос на скуле...    
|Select                    
   |      case
   |        when
   |            LEFT(Спр.SP7835,1)='М'
   |        then
   |            CAST(SUBSTRING(Спр.SP7835,CHARINDEX('0',Спр.SP7835,0),LEN(Спр.SP7835)) as int)    
   |        else                                                                                
   |            CAST(Спр.SP7835 as int)    
   |    end as NomCode  
   |INTO #TBL
   |FROM
   |     $Справочник.Номенклатура as Спр      
   |    
   |WHERE    
   |    LEFT(Спр.SP7835,1)!='М'
   |        
   |ORDER BY    
   |    NomCode;
   |
   |Select * FROM #TBL
   |

Но проблема в том что при однократном создании, временная таблица создается, а при повторном вылазит ошибка. Что объект уже есть. Я так понимаю в tempdb и второе ... в этому же запросе второй раз SELECT к временной таблице не работает.  Нужно делать второй запрос.
ЗЫ: Проверил после создания временной таблицы и потом обратившись только к ней.

Как быть в моем случае? Гуру скулей подскажите?  Делать подзапрос?
50 АгентБезопасной Нацио
 
04.09.19
14:53
drop table #TBL
51 uno-group
 
04.09.19
14:54
Собираешь самый большой справочник из всех баз. делаешь сводную таблицу старый код-новый код. Делаешь обработку которая переномеровывает согласно данной таблице справочник. Запускаешь обновление кодов во всех базах.
52 АгентБезопасной Нацио
 
04.09.19
14:57
(51) ... затем перепечатываешь все ценники, паспечатыаешь и отправляешь во все филиалы, соотвествующие базам. И заставляешь всех операторов перезапомнить коды.
делов-то....
:-)
53 uno-group
 
04.09.19
15:07
(52) На ценники нужно печатать штрихкод, а не внутренний код.
54 АгентБезопасной Нацио
 
04.09.19
15:10
(53) ...и каждому покупателю давать сканер штрих-кода. в подарок.
55 brenli
 
04.09.19
15:11
(53) Заведен внутренний код, я не собираюсь им что то переделывать. Одно время они использовали сканеры ШК. Но почему то предпочли коды. ХЗ.
56 brenli
 
04.09.19
15:13
Специфика организации большой ассортимент металлопроката и крупногабаритных товаров которые на кассу не доставишь. Понятно можно завести тетрадь со ШК но видимо им так удобнее.Пусть робят так
57 АгентБезопасной Нацио
 
04.09.19
15:16
млин, ну поставлен у людей БП так, что на ценнике в торговом зале напечатан короткий код. короче, чем штатный код - чтоб было быстрее вводить. и покупатель ходящий по залу, кричит продавцу - "32345 - одын штюка, 78512 - тры штюка, сёё!"
или пишет на бумажке, и затем подходит и диктует. а некоторые ходовые позиции запомнены продавцом наизусть, чтоб не посылать покупателя повторно по залу. схема более чем частая в магазинах метизов, электрики, отделочных материалов, радиодеталей.
вполне имеет право на жизнь.
я вообще не понимаю проблем ТС - решение ему дали еще вчера...
58 brenli
 
04.09.19
15:25
(57)
Вы все верно сказали. Браво!!!

Занимаюсь реализацией) возникли небольшие трудности с реализацией запросов. Разбираюсь
59 Сияющий в темноте
 
04.09.19
15:27
Быстрый код-это,обычно,отдельный справочник и его элементы привязываются к номенклатуре,причем,не всегда к одной(тогда касса просит выбрать)и,со временем,привязку можно менять,если меняется товар.
непривязанные элементы можно считать свободными.
если кассовая программа не умеет быстрые коды,то они выгружаются как штрихкоды,можно ч префмксом,тогда на клавиатуре нужно кнопку макроса программировать.
в каждом магазине быстрый код свой.
первую сотню,обычно,на наиболее частый товар.
можно делать несколько групп быстрых кодов,если использовать наклейки разных цветов,получается очень удобно для разных групп товаров.
60 uno-group
 
04.09.19
15:40
Если есть куча баз то не факт, что дырка в 1 базе является дыркой в другой и в результате занятия дырок не получиться, что при экспорте труба не превратиться в лист и т.п.
61 brenli
 
04.09.19
15:47
(60) База распределенная.
62 uno-group
 
04.09.19
15:49
При создании нового элемента в параллельном потоке запускаешь поиск свободного кода. Пока пользователь заполнит данные новой карточки свободный код найдется.
63 АгентБезопасной Нацио
 
04.09.19
17:39
(60) факт.прицентрализованном вводе факт
64 brenli
 
06.09.19
09:34
Всем спасибо господа.
С небольшими доработками идея реализована.
SQL рулит бесспорно.
Результат формирования кода на прямых запросах = 1 сек.
65 brenli
 
06.09.19
09:35
(48) Отдельное спасибо . Взята ваша идея за основу
66 brenli
 
06.09.19
09:37
А вот и сам текст запроса для SQL базы

    |Select  
    |    MAX(OneQuery.NomCode)   as max_number,
    |    MIN(OneQuery.NomCode-1) as result
    |FROM
    |    (Select                    
    |        CAST(Спр.SP7835 as int)    as NomCode
    |    FROM
    |         $Справочник.Номенклатура as Спр      
    |    WHERE    
    |        LEFT(Спр.SP7835,1)!='Ì' and Спр.IsFolder = 2
    |    ) as OneQuery
    |
    |LEFT JOIN
    |
    |    (Select                    
    |        CAST(Спр.SP7835 as int) as NomCode    
    |     FROM
    |         $Справочник.Номенклатура as Спр      
    |    WHERE    
    |        LEFT(Спр.SP7835,1)!='Ì' and Спр.IsFolder = 2
    |    ) as OneQuery2  
    |
    |    ON OneQuery.NomCode = OneQuery2.NomCode+1
    |WHERE        
    |    OneQuery2.NomCode Is Null  and OneQuery.NomCode!=0
    |";
67 Salimbek
 
06.09.19
09:56
(66) Маленькое замечание - если уж используешь 1С++, то можно вместо Спр.SP7835 использовать $Спр.ТвойРеквизитСКодом