Имя: Пароль:
1C
1С v8
Найти первый свободный артикул
,
0 sergqwert
 
13.08.21
13:41
Есть стандартный справочник номенклатуры, у которого есть реквизит – числовой артикул.
В справочнике большое количество элементов. Некоторые могут удаляться. Как найти первый свободный артикул (либо все незанятые артикулы). То число, которое не принадлежит ни одному из элементов справочника. Перебор использовать нельзя.
1 ДенисЧ
 
13.08.21
13:42
2 DrShad
 
13.08.21
13:43
собери в запросе таблицу чисел, потом соедини со своим справочником, где будет NULL там и свободно, выбрать минимум
3 fisher
 
13.08.21
13:46
Если для целей "заполнения дырок" (т.е. реализации собственной нумерации без пропусков) - нужно вести учет дырок.
Если просто странная алгоритмическая задача, то можно проверять "куски" диапазонов с половинным делением - если количество элементов в куске "стыкуется" с первым и последним номером, значит в этом диапазоне дырок нет.
4 Classic
 
13.08.21
13:50
ВЫБРАТЬ
    0 КАК Артикул
ПОМЕСТИТЬ Артикулы
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
    СправочникНоменклатура.Артикул
ИЗ Справочник.Номенклатура КАК СправочникНоменклатура
;
ВЫБРАТЬ
    МИНИМУМ(Артикулы.Артикул) + 1
ИЗ Артикулы КАК Артикулы
   ЛЕВОЕ СОЕДИНЕНИЕ Артикулы КАК Артикулы.Следующий
   ПО Артикулы.Артикул + 1 = АртикулыСледующий.Артикул
ГДЕ
   АртикулыСледующий.Артикул ЕСТЬ NULL
5 H A D G E H O G s
 
13.08.21
13:56
(4) У вас - перебор. Использовать нельзя, см (0)
6 Kassern
 
13.08.21
13:57
(0) тестовое задание?
8 Kassern
 
13.08.21
14:02
(0) посмотрите как в типовых новый ШК присваивается
9 Garykom
 
гуру
13.08.21
14:03
(0) засунь в ТЗ и отсортируй, далее один проход
10 серый КТУЛХУ
 
13.08.21
14:04
половинное деление с определением наличия дырок в интервале по не равенству дельты кон.артикула минус нач.артикула + 1 от количества значений в интервале.
11 Classic
 
13.08.21
14:04
(5)
Артикул = СлучайноеЧисло();
Если ЗначениеЗаполнено(Справочник.Номенклатура.НайтиПоРеквизиту("Артикул", СлучайноеЧисло)) Тогда
    Сообщить("Объекты базы заблокированы бухгалтерией. Попробуйте еще раз позже");
КонецЕсли;

Так пойдет?
12 Garykom
 
гуру
13.08.21
14:05
(10) не сильно лучше полного перебора
13 серый КТУЛХУ
 
13.08.21
14:05
(10)+: конечно по отсортированной по возрастанию артикула выборке.
(12): в два раза лучше - это "сильно лучше"
14 Garykom
 
гуру
13.08.21
14:07
(13) в два раза это идеальная нач ситуация
на практике на условиях и обращениях с вычислениями потеряешь больше чем банальный цикл со сравнением пар
15 Garykom
 
гуру
13.08.21
14:08
и метод половинного хреново параллелится
в отличие от совмещения сортировки с определением интервалов
16 серый КТУЛХУ
 
13.08.21
14:08
(14): нет, не идеальная.
17 Classic
 
13.08.21
14:10
(15)
Половинное хреново параллелится?
18 серый КТУЛХУ
 
13.08.21
14:10
(15): схреновли он "храново параллелится".
храново параллелится он у тех кто хреново параллетит. два потока - сразу четверное деление и ускорение по сравнению с перебором в 4 раза. четыре потока - ускорение по сравнению с перебором в 16 раз.
19 Serg_1960
 
13.08.21
14:15
(0) Спасибо за интересный вопрос :)

    Запрос = Новый Запрос;
    Запрос.Текст =
    "ВЫБРАТЬ ПЕРВЫЕ 999999
    |    ВсеАртикулы.Артикул КАК Артикул,
    |    АВТОНОМЕРЗАПИСИ() КАК Номер
    |ПОМЕСТИТЬ ВТ
    |ИЗ
    |    Справочник.Номенклатура КАК ВсеАртикулы
    |ГДЕ
    |    ВсеАртикулы.Артикул <> 0
    |
    |УПОРЯДОЧИТЬ ПО
    |    Артикул
    |;
    |
    |////////////////////////////////////////////////////////////////////////////////
    |ВЫБРАТЬ ПЕРВЫЕ 1
    |    НеЗанятые.Номер КАК СвободныйНомер
    |ИЗ
    |    ВТ КАК НеЗанятые
    |ГДЕ
    |    НеЗанятые.Артикул <> НеЗанятые.Номер
    |
    |УПОРЯДОЧИТЬ ПО
    |    СвободныйНомер";
20 Kassern
 
13.08.21
14:17
(19) артикул с кодом 1000000, ну да пошел я на*ер=))
21 Serg_1960
 
13.08.21
14:20
(20) Добавь девяток столько, сколько длина артикула. Разрешаю.
22 PLUT
 
13.08.21
14:22
(0) Артикул - тип Строка (50)  в ERP
23 Garykom
 
гуру
13.08.21
14:23
(17) (18) распишите алгоритм распараллеливания половинного
24 Kassern
 
13.08.21
14:26
(21) насколько мне известно, максимум вы сможете выбрать 1410065407. А артикул это 99% у ТС строка скорее всего длинной в 50символов.
25 mistеr
 
13.08.21
14:35
(0) Как ни крути, а на уровне скуля все равно будет перебор. Препода, задавшего задачу, на мыло!

(24) Сказано же, число.
26 Garykom
 
гуру
13.08.21
14:37
(25) именно перебор
27 Kassern
 
13.08.21
14:37
(25) читайте внимательно: (0) "стандартный справочник номенклатуры, у которого есть реквизит – числовой артикул"
Насколько я понял, это значит, что в строковое поле Артикул стандартного справочника номенклатуры записывается число. Пример артикул "123456", полностью подходит под описание ТС
28 Kassern
 
13.08.21
14:38
(27) в общем, как то двояко воспринимается его текст. Лучше бы написал, реквизит с типом таким то.
29 Serg_1960
 
13.08.21
14:42
Это всего лишь игры разума :)
30 серый КТУЛХУ
 
13.08.21
14:51
(23): ты идиот? (18) по слогам перечитай. немного подумай.
в каждом потоке - получение интервала, проверка на наличие в нем "дырки":
есть дырка - делим на количество "свободных" потоков (включая себя) и раздаем
нет дырки - отбрасываем интервал и переходим в статус "свободного".
на пальцах. 4 параллельных потока вычислений. начальный интервал 1-80 дырка в последнем проверяемом (пессимистический случай, полный перебор = 80 тактов)
1 такт.
1-й поток - получил интервал 1-20 проверил - дырок нет - освободился.
2-й поток - получил интервал 21-40 проверил - дырка есть - разделил на 4 интервала для раздачи...
3-й поток - получил интервал 41-60 проверил - дырок нет - освободился.
4-й поток - получил интервал 61-80 проверил - дырок нет - освободился.
2 такт.
1-й поток - получил интервал 21-25 проверил - дырок нет - освободился.
2-й поток - получил интервал 26-30 проверил - дырка есть - разделил на 4 интервала для раздачи...
3-й поток - получил интервал 31-35 проверил - дырок нет - освободился.
4-й поток - получил интервал 36-40 проверил - дырок нет - освободился.
3 такт - финиш. однозначное определение дырки.
3 такта (или пусть даже 5 при затрате на каждую раздачу по такту) а не 80 для перебора - при пессимистическом исходе.
31 серый КТУЛХУ
 
13.08.21
14:54
если неймется - можно попробовать сыграть на четырех сеансах и одном регистре сведений.
32 Garykom
 
гуру
13.08.21
14:54
(30) >проверка на наличие в нем "дырки"

каким образом выполняется?
33 серый КТУЛХУ
 
13.08.21
14:56
(32): см.(10) "по не равенству дельты кон.артикула минус нач.артикула + 1 от количества значений в интервале."
(ты вообще читаешь на что отвечаешь и прямо к нему относящееся?)
34 Garykom
 
гуру
13.08.21
14:57
(33) как найдется конечный и начальный артикулы в интервале?
с чего взял что у тебя артикулы отсортированы?
35 серый КТУЛХУ
 
13.08.21
14:58
ЗЫ: вообщек надо Ваню Guk-а позвать - он и про это разжует и еще более оптимальных алгоритмов может быть отсыпет. с точным определением их сложности.
39 Йохохо
 
13.08.21
15:15
(14) добавь проверку что свободные не макс +1, получишь ускорение на два порядка)
40 Garykom
 
гуру
13.08.21
15:20
(39) тут есть всего два вида перебора

перебирать весь интервал (проверяя каждое число от 1 до N есть ли оно в артикулах в справочнике) и перебирать все занятые (артикулы из справочника, размещая/сортирую а затем проверяя попарно нет ли разрыва)

все

все методы прочие это вариации этих двух по совмещению
41 nodrama
 
13.08.21
15:50
(0) Если Артикул числовой. Значит база не типовая. в типовых он вроде "строка" ))

Вообще артикулы так себе штука.. помню был интернет магаз большой. у них УТ была. Они покупали кууууеву тучу товаров у поставщиков
И что. один и тот де товар у разных поставщиков может быть с разными артикулами в прайсах.
один и тот же артикул у тебя в базе у разных поставщиков может использоваться в разных товаров

У тебя Отвертка артикул 123456
А у поставщика артикул 123456 это Шуруп а ты у этого поставщика покупаешь 10к+ позиций по прайсу каждый месяц.
Получается к артикулу привязываться уже нельзя при таких объемах и продажах и количестве поставщиков.

А в свой интернет магаз ты выгружаешь со своими артикулами те которые загрузились с прайсов ранее и были свободными. Либо у тебя будет два разных товара с одним артикулом что не верно

В общем Артикулы так себе реквизит
42 nodrama
 
13.08.21
15:51
(41) И получается что бы загрузить этот шуруп из прайса с 10к позициями. тебе не нужно привязываться к артиклу что логично.
Только у тебя может быть точно такой же Шуруп только чуть другое название. СРазу нужно делать "Аналоги номенклатуры" в общем.. напомнили мне геморой ))
43 Garykom
 
гуру
13.08.21
15:53
(41) думаю это внешние id фактически, которые просто а артикулах в конфе хранят
44 Kassern
 
13.08.21
15:56
(41) вы не поверите, есть такой справочник, как НоменклатураКонтрагентов (раньше НоменклатураПоставщиков была). Вот он и юзается для таких задач
45 МихаилМ
 
13.08.21
18:29
46 Злопчинский
 
13.08.21
19:01
(3) "то можно проверять "куски" диапазонов с половинным делением"
- это вариант перебора, а перебор - нельзя
47 Вафель
 
13.08.21
19:53
Для каждого найти следующий (а ля срез последних)
Если слнд не равен +1, тогда вот он свободный номер
48 Garykom
 
гуру
13.08.21
19:55
(47) это самый дебильный вариант запроса в цикле перебора
49 Вафель
 
13.08.21
20:34
(48) в каком цикле?
50 Вафель
 
13.08.21
20:35
Там не перебор, мердж скорее всего будет
51 Йохохо
 
13.08.21
20:39
вариант Сердж_1960 через ИМЕЮЩИЕ не будет иметь цикла даже в трансляции скуля
52 Йохохо
 
13.08.21
20:42
хотя цикла фор там все равно будет минимум 4)
53 DJ Anthon
 
13.08.21
20:45
(8) берется последнее в каждом поддиапазоне, там не поиск дырок
54 Кирпич
 
13.08.21
21:13
(0)Ну так можно. Выбрать начала всех дырок

ВЫБРАТЬ
   А.Код + 1
   ИЗ Справочник.Товары КАК А
   ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Товары КАК Б
        ПО А.Код = Б.Код - 1
   ГДЕ Б.Код - 1 IS NULL;
55 ДедМорроз
 
14.08.21
12:17
Только выбрать первые 1 и упорядочить по коду,чтобы скуль не шарил всю таблицу.
56 ДедМорроз
 
14.08.21
12:19
Печаль этого действа в том,что если дырок нет,то будет полное сканирование всец таблицы,точнее индекса,нл все равно это долго.
57 mistеr
 
14.08.21
16:00
(56) Другими словами, будет перебор.
58 Garykom
 
гуру
14.08.21
16:17
(57) Задаче без перебора решается только если при удалении артикула (очистка/изменение реквизита у элемента справочника или удаление элемента) писать его в РС свободных
59 серый КТУЛХУ
 
14.08.21
17:42
с терминологией сначала определиться бы. а то в интертрепации некоторых оппонентов реребором можно назвать любой выбор элементов, более одного: аааа, выбрал второй элемент - перебооорррр...
ну или бинарный поиск (например) - не перебор. ))))
60 Garykom
 
гуру
14.08.21
17:51
(59) чтобы индекс построить сначала нужен полный перебор
61 MyNick
 
14.08.21
18:12
(0) в рег сведений писать дырки, при занятости удалять
62 MyNick
 
14.08.21
18:14
+ (61) работать будет одинаково эффективно хоть на тыще записей, хоть на миллионе. В отличие от всяких переборов и прочих вангований.
63 Кирпич
 
14.08.21
18:54
Так без перебора не получится никак. Это невозможно сделать без перебора. Только если создавать специальный индекс.
64 Aleksey
 
14.08.21
18:57
А зачем артикул, который не уникален?
65 Кирпич
 
14.08.21
19:21
(64) Да это просто задачка наверное
66 Lexandr
 
14.08.21
19:34
(63) Ну или добавить в базу новый объект с помощью которого будет искаться нужный артикул за одно обращение. Если задача синтетическая, то можно добавлять окружение, как вот прям захочется.
67 VS-1976
 
14.08.21
20:48
Что бы сократить ресурсы на поиск теоретически можно сделать так:

Вызывать в цикле запрос отбирая окнами артикула, пока не найдёшь разрыв. К примеру по 100-500 артикулов за раз.
Ну а потом в этом диапазоне вытащив на клиент, уже можно найти разрыв.

ВЫБРАТЬ
    1 КАК Группа,
    Истина КАК ЕстьРазрывы
ИЗ
    Справочник.Номенклатура КАК Номенклатура
ГДЕ
    Артикул МЕЖДУ &НачАртикул И &КонАртикул

СГРУППИРОВАТЬ ПО
    1
ИМЕЮЩИЕ
    КОЛИЧЕСТВО( Артикул ) < &КоличествоАртикулов // КонАртикул - НачАртикул
68 VS-1976
 
14.08.21
20:50
(67) После нахождения свободного артикула, можно куда нибудь записывать его значение, чтобы в последующем стартовать от него + 1
69 VS-1976
 
14.08.21
20:51
(68) Хотя если освободиться может любой... то пожалуй нет
70 VS-1976
 
14.08.21
20:56
(67) Так красивее немного

оЗапрос = Новый Запрос( "ВЫБРАТЬ
    Истина КАК ЕстьРазрывы
ИЗ
    Справочник.Номенклатура КАК Номенклатура
ГДЕ
    Артикул МЕЖДУ &НачАртикул И &КонАртикул

СГРУППИРОВАТЬ ПО
    1
ИМЕЮЩИЕ
    КОЛИЧЕСТВО( Артикул ) < &КоличествоАртикулов" );

...

Если Не оЗапрос.Выполнить().Пустой() Тогда

    // Выбираем диапазон и ищем на клиенте разрыв или с помощью запроса, предложенного ранее с +1 к артикулу.

КонецЕсли;
71 Garykom
 
гуру
14.08.21
21:24
Странные люди, не понимающие что никакие запросы кроме как получения всех артикулов тут не нужны
Затем берется "массив" (в кавычках потому что на 1С массивы не совсем они и лучше что то иное) длиной в максимальный артикул, изначально заполненный 0
И тупо туда пишутся 1 по адресам = артикулам

Далее останется только пробежаться по "массиву" и вот пустые артикулы где 0 остался
72 Кирпич
 
14.08.21
22:00
(71) Бухаешь?
73 Garykom
 
гуру
14.08.21
22:07
(72) мне бухать здоровье не позволяет
остается только флудить и троллить на форумах
74 Вафель
 
14.08.21
22:08
(71) уж лучше делением пополам
75 VS-1976
 
14.08.21
22:13
(71) Думаю проще как у меня сделать, окнами вынимать данные. Если артикулов много то I/O будет большой. А так как мой запрос не пересоздаётся, а подкидываются свежие параметры, то и запрос отрабатывает быстро, так как не нужен парсинг запроса и построение плана исполнения, тупо выбираются только данные. Далее данные которые уже в кэше ( последнее окно ) быстро вытаскиваются на свет, при их анализе.
76 VS-1976
 
14.08.21
22:15
(75) К примеру артикулов миллион, если брать окна по 1000 то будет 1000 запросов. Количество окон можно регулировать. К примеру хотим максимум 100 запросов, тогда 1 000 000 / 100 - окно = 10 000 артикулов
77 VS-1976
 
14.08.21
22:19
(76) К стати МАКСИМУМ( Артикул ) отрабатывает мгновенно, так как это упорядоченный "массив" - есть индекс. И таблица в шапке содержит ссылку на последний элемент, для последующей вставки в таблицу
78 Garykom
 
гуру
14.08.21
22:21
(74) Не поможет тут никакое деление кроме как на потоки
79 Garykom
 
гуру
14.08.21
22:23
(76) а сообразить что все эти запросы будут к одной табличке?

(77) индекса на поле Артикул может не быть, он может быть строковым в этом случае какой в жпо максимум?
80 VS-1976
 
14.08.21
22:26
(79) Читай заголовок:
Есть стандартный справочник номенклатуры, у которого есть реквизит – числовой артикул.
У номенклатуры артикул в индексе, так как поиск по артикулу - "Будь готов, всегда готов"

И что, что запросы к одной таблице? Даже индекс читается кусками )

PS: Зачем фантазировать то?
81 Garykom
 
гуру
14.08.21
22:28
(80) артикул то числовой а вот реквизит не факт
82 Garykom
 
гуру
14.08.21
22:29
(81)+ Логично что если это типовая конфа то там Артикул по дефолту строка, просто они туда id пишут числовые
83 VS-1976
 
14.08.21
22:31
(82) Число, строка какая для бинарного сравнения разница ). Это для тебя строка, а для процессора поток битов )
84 Garykom
 
гуру
14.08.21
22:31
(80) И насчет запросов.
Самое быстро это один запрос который полные данные выдаст а не куча кусочных одновременно
И далее полученные обрабатываем по (71)

Вот я готов на поспорить что мой метод самый быстрый чем ваши с кучей запросов, на одинаковом железе и базе
85 Garykom
 
гуру
14.08.21
22:31
(83) ыыы
86 Garykom
 
гуру
14.08.21
22:32
меня иногда удивляет как люди с подобным незнанием основ умудряются работать да еще и зарплату получать
87 VS-1976
 
14.08.21
22:33
(84) Как бы всё зависит от количества и от того, как часто в "окнах" появляются пробелы
88 VS-1976
 
14.08.21
22:34
(86) Хотя бы приводил про кого речь ведёшь, а то я тоже могу абстрактно пукать не хуже )
89 Garykom
 
гуру
14.08.21
22:48
(88) >Число, строка какая для бинарного сравнения разница ). Это для тебя строка, а для процессора поток битов

процессоры давным-давно уже не битами оперируют а большими объемами
обработка чисел, строк, дат, булевых, ссылочных и т.д. отличается
в случае строк переменной длины (тип varchar) особенно
90 VS-1976
 
14.08.21
22:58
(89) Да ладно, честно что ли ), 64-ре бит, да не ужели... ты открыл истину для человека, который писал на assembler-е
91 Garykom
 
гуру
14.08.21
23:03
(90) ничего страшного что забыл это просто возрастное, попей ривастигмин или аналоги
но пора уже программирование и ИТ бросать, да
92 VS-1976
 
14.08.21
23:05
(90) Скажи а SSE позволяет параллельно обрабатывать 8 байт без переноса знака в старший разряд для мультимедиа, это же куруть! Прикинь сложение и т.д. сразу 8-ми чисел, я не говорю о сопроцессоре i87. Ты мой бог, присылай фото, рамку для иконы я уже вытачиваю )
93 VS-1976
 
14.08.21
23:06
(91) Хоре курить, понимаю что не пьёшь, но дурь тоже не полезна )
94 Garykom
 
гуру
14.08.21
23:09
(92) ты уже сам с собой разговариваешь? у себя спрашиваешь?
95 VS-1976
 
14.08.21
23:11
(94) Да мне то что с тобой разговаривать то ). Смысл? Ты как бы капитан очевидность, но непонятно как это относится к конкретной задаче? Я понимаю что выкуривая штакетник тянет на абстракции )
96 ДедМорроз
 
15.08.21
08:28
Индекс по артикулу строится в процессе работы,так как по нему идет поиск.
Поиск свободного - это,по сути,перебор,то есть полное сканирование индекса.
Таблица индекса - это артикул и кластерный инндекс записи таблицы - для справочника - это уникальный идентификатор.
То есть,перебор индекса не требует перебора записей,а индекс явно занимает меньше места в страницах.
Однако,операция все равно ресурсоемкая.
Поэтому,в реальности,проще хранить где-то свободные артикулы.

Но,если у пользователя на форме есть кнопка СвободныйАртикул,то время его поиска будет не критично,т.к.открытие и заполнение формы руками - это долго,и подьзователь ничего не заметит.

Если же пакетно идет добавление записей и нужны свободные артикулы,то проще одним запросом ввбрать их все,которые меньше максимального и из подготовленной таблицы уже доставать в процессе заполнения.
Но,тут нужно помнить про синхронизацию
Свободный артикул свободен,пока не создана запись с ним,поэтому несколько одновременных процессов получат один и тот же список свободных артикулов - это очень важно понимать,т.к.в процесс поиска и лбработки нужно будет добавить синхронизацию,чтобы один поток,получив артикул,мог его записать в базу,не боясь,что его кто-то другой запишет раньше него.
В 1с номера документов работают примерно так,но там есть таблица занятых номеров,хотя,номер присваивается при записи.