|
Найти и использовать пропущенный номер | ☑ | ||
---|---|---|---|---|
0
cry_san
17.04.13
✎
05:27
|
Здравствуйте!
Есть справочник без сторонних реквизитов (только Код и Наименование). Код можно заполнять произвольно, но стоит галочка на уникальность. Как можно (и можно ли) ОДНИМ запросом найти первый (в порядке возрастания) пропущенный номер и использовать его (причем так, чтобы другой пользователь в этот момент не успел подхватить тот же номер). Спасибо! |
|||
1
alkorolev
17.04.13
✎
05:46
|
префикс в коде есть?
|
|||
2
golden-pack
17.04.13
✎
05:46
|
1. Как можно (и можно ли) ОДНИМ запросом найти первый (в порядке возрастания) пропущенный номер и использовать его
- ответь на вопрос - как можно найти не запросом 2.(причем так, чтобы другой пользователь в этот момент не успел подхватить тот же номер). - никак |
|||
3
IamAlexy
17.04.13
✎
05:52
|
(2) сам такой херней не маялся но чисто в теории:
1. предварительно заполнить таблицу значений из номеров затем скормить ее запросу присоеденив объекты по номеру и выбрав первую позицию с отсутствующим объектом 2. заблокировать на время всего этого действа объект типа блокировками типа управляемыми. |
|||
4
alkorolev
17.04.13
✎
05:52
|
Если префикса нет, то что-то типа этого:
получаешь последний код справочника, преобразуешь его в число. Затем: Для к = 1 по ПоследнийКод КодСтрока = Формат(к, "ЧЦ=9; ЧВН=; ЧГ="); НайденныйЭлемент = Справочники.ТвойСправочник.НайтиПоКоду(КодСтрока); Если НайденныйЭлемент.Пустая() Тогда // код свободен ... |
|||
5
alkorolev
17.04.13
✎
05:53
|
в Формат(к, "ЧЦ=9; ЧВН=; ЧГ=") ты преобразуешь число обратно в код. ЧЦ=9 - допустимая длина кода, ЧВН - вы вод лидирующих нулей, ЧГ - без групппировок. Т.е. число 1 представляешь в виде "000000001"
|
|||
6
cry_san
17.04.13
✎
06:20
|
(1) Префикса нет - только ведущие нули
|
|||
7
cry_san
17.04.13
✎
06:21
|
(4) НайтиПоКоду в цикле не сильно будет тормозить программу?
|
|||
8
cry_san
17.04.13
✎
06:22
|
(2) Можно. Ответ почти такой же как и в (4)
|
|||
9
Evpatiy
17.04.13
✎
06:29
|
Ну на вскидку можно просто объединить таблицу номеров саму с собой и найти те номера для которых в Таблица2 нет номера равного Таблица1.Номер+1. Отсортировать их в порядке возрастания и выбрать первый. Чтобы другой пользователь не влез просто блокируй таблицу.
|
|||
10
Evpatiy
17.04.13
✎
06:30
|
(7) Запрос в данном случае скорее всего будет предпочтительнее.
|
|||
11
Evpatiy
17.04.13
✎
06:30
|
+(10) С точки зрения производительности
|
|||
12
cry_san
17.04.13
✎
06:30
|
(10) Ну так это понятно, но как это сделать запросом?
|
|||
13
Evpatiy
17.04.13
✎
06:31
|
(12) В 9 написал вариант.
|
|||
14
cry_san
17.04.13
✎
06:34
|
Сделал так:
Запрос = Новый Запрос; Запрос.Текст = " |ВЫБРАТЬ ПЕРВЫЕ 1 | Код |ИЗ | Справочник.Реестр |УПОРЯДОЧИТЬ ПО | Код УБЫВ"; Выборка = Запрос.Выполнить().Выбрать(); Если Выборка.Следующий() Тогда ПоследнийКод = Выборка.Код; КонецЕсли; Сообщить(ПоследнийКод); Для к = 1 по Число(ПоследнийКод) Цикл КодСтрока = Формат(к, "ЧЦ=6; ЧВН=; ЧГ="); Сообщить("КодСтрока = " + Строка(КодСтрока)); НайденныйЭлемент = Справочники.Реестр.НайтиПоКоду(КодСтрока); Если НайденныйЭлемент.Пустая() Тогда Сообщить(НайденныйЭлемент.Ссылка.Код); КонецЕсли; КонецЦикла; Но не выводит код |
|||
15
Галахад
гуру
17.04.13
✎
06:35
|
Гм, а как это Таблица1.Номер+1 сработает при строковых дынных как у ТС?
|
|||
16
Галахад
гуру
17.04.13
✎
06:36
|
(14) Вариант (3) получше.
|
|||
17
cry_san
17.04.13
✎
06:39
|
(16) Согласен. Но пока не хватает теорзнаний для создания подобного ((
|
|||
18
cry_san
17.04.13
✎
06:43
|
(14) Поправил на
Для к = 1 по Число(ПоследнийКод) Цикл КодСтрока = Формат(к, "ЧЦ=6; ЧВН=; ЧГ="); Сообщить("КодСтрока = " + Строка(КодСтрока)); НайденныйЭлемент = Справочники.КПК_РеестрПайщиков.НайтиПоКоду(КодСтрока); Если НайденныйЭлемент.Пустая() Тогда Сообщить(КодСтрока); КонецЕсли; КонецЦикла; Однако, если последнее число за 10000 - сильные тормоза - ждет пока переберет до последнего, если пропущенный номер 9999 |
|||
19
Evpatiy
17.04.13
✎
06:47
|
(15) У ТС нет префиксов, можно преобразовать в запросе в число.
|
|||
20
Галахад
гуру
17.04.13
✎
06:48
|
(19) Подскажи как строку преобразовать в число.
|
|||
21
cry_san
17.04.13
✎
06:48
|
(20) Число();
|
|||
22
Галахад
гуру
17.04.13
✎
06:48
|
(21) В запросе?
|
|||
23
cry_san
17.04.13
✎
06:51
|
ВЫБРАТЬ
10/3 ВЫРАЗИТЬ КАК ЧИСЛО(15,2) КАК Цена |
|||
24
cry_san
17.04.13
✎
06:52
|
||||
25
Галахад
гуру
17.04.13
✎
06:54
|
(23) Ага. А так:
ВЫБРАТЬ "10" ВЫРАЗИТЬ КАК ЧИСЛО(15,2) КАК Цена |
|||
26
1Сергей
17.04.13
✎
06:54
|
(24) по твоей ссылке большое предупреждение:
"В запросах 1С с помощью функции ВЫРАЗИТЬ преобразовать строку в число нельзя" |
|||
27
Галахад
гуру
17.04.13
✎
06:55
|
(24) А, ты уже понял.
|
|||
28
cry_san
17.04.13
✎
06:56
|
(27) Угу. Вернемся к (3). Практические идеи есть?
|
|||
29
IamAlexy
17.04.13
✎
06:58
|
(28) практическая идея: сесть и сделать..
каждый шаг моего гениального зловещего плана более чем реален. что именно вас смущает в идее? |
|||
30
IamAlexy
17.04.13
✎
06:59
|
да на фейхоа что либо куда преобразовывать?
сделайте генератором номера в том же формате в котором они есть. заполните в базу и объеденяйте по номеру.. префикс? текст? да пофиг.... |
|||
31
Evpatiy
17.04.13
✎
06:59
|
(20) Вытащить в таблицу значений и преобразовать, вернуть в запрос.
|
|||
32
1Сергей
17.04.13
✎
06:59
|
(29) >>предварительно заполнить таблицу значений из номеров...
Перебор справочника будет быстрее |
|||
33
Галахад
гуру
17.04.13
✎
06:59
|
(28) Ну вроде там описано.
1. Таблица 0001 0002 ... 0N 2. К ней левым соединением таблицу номеров. 3. Где номер = null это и есть пропуски. |
|||
34
IamAlexy
17.04.13
✎
07:01
|
(32) да что вы говорите...
|
|||
35
cry_san
17.04.13
✎
07:04
|
(32) Забил последним 25000. Пустой сделал 24999. Сижу уже 6 минут.
|
|||
36
NWsFF
17.04.13
✎
07:08
|
(9) Идея на столько хороша, что я бы поменяль тип кода на число.
|
|||
37
IamAlexy
17.04.13
✎
07:12
|
(35) сделай как с календарем..
регистр сведений с миллионом записей :) и к нему цепляй запросом :) :) |
|||
38
cry_san
17.04.13
✎
07:13
|
(37) Ага, ждите )))
|
|||
39
IamAlexy
17.04.13
✎
07:15
|
(38) а кстати это вариант...
один раз заполнил регистр сведений "зарезервированныеномера" и далее запросом просто получаешь свободный номер. если эта операция частая - в итоге будет экономия... |
|||
40
kosts
17.04.13
✎
07:17
|
Перевод строки в число, при условии, что номера строго в формате "00001" (иначе еще в правильный формат нужно перевести)
Хотя ноль можно совсем выкинуть... |
|||
41
IamAlexy
17.04.13
✎
07:18
|
(40) номера допустим с префиксами...
|
|||
42
cry_san
17.04.13
✎
07:19
|
(41) В конкретной задаче без префиксов
|
|||
43
cry_san
17.04.13
✎
07:20
|
(39) Интересный вариант. Операция частая.
"далее запросом просто получаешь СВОБОДНЫЙ номер" - пример можно? |
|||
44
kosts
17.04.13
✎
07:22
|
(43) Нужно устранить причину появления дырок в нумерации - запретить запись не по порядку
|
|||
45
IamAlexy
17.04.13
✎
07:26
|
(43) естьnull(номенклатура.номер,0)
затем сортировка по возрастанию и выбор первого значения. |
|||
46
kosts
17.04.13
✎
07:27
|
(43) >Частая операция
Это сколько раз в сутки? Если не тысячи, то нет смысла создавать регистр |
|||
47
IamAlexy
17.04.13
✎
07:28
|
ну или чтобы текстовые номера сожрать:
выбор когда номенклатура.номер есть null тогда истина иначе ложь конец и далее сортировка и выбор первого (ну или последнего) - не помню чо там первее отсортируется... |
|||
48
IamAlexy
17.04.13
✎
07:28
|
(46) да там пофиг..
если частая - то регистр если редкая - то заполняем таблицу значений номерами,передаем запрос и к ней цепляемся слева... |
|||
49
IamAlexy
17.04.13
✎
07:29
|
это я к тому что не надо усложнять.. делать 100этажные запросы по преобразованию строк в числа и только ради того чтобы через месяц упереться в то что некий гений ввел номер типа 0001000/1 и вся нумерация накрылась раком
|
|||
50
kosts
17.04.13
✎
07:30
|
Если добавлять что-то в базу, то тогда лучше в этот же справочник добавить числовой реквизит и заполнять его при записи. Запросы по нему делать.
|
|||
51
cry_san
17.04.13
✎
07:31
|
(46) 10-100 раз
|
|||
52
kosts
17.04.13
✎
07:31
|
(49) Тем же раком накроется и регистр. Гадать можно долго. Пусть ТС решит для себя что ему проще...
|
|||
53
kosts
17.04.13
✎
07:33
|
(51) Ну тогда я бы не стал базу менять.
|
|||
54
cry_san
17.04.13
✎
07:33
|
(53) Послушаюсь вас.
|
|||
55
IamAlexy
17.04.13
✎
07:34
|
(52) в том то и прикол - не накроется...
подумай чуть то.. база увидит что есть свободный номер и назначит его.. то есть пользовательская корявка со слешами будет проигнорирована и нумерация не уйдет в ступор при достижении .../9 |
|||
56
kosts
17.04.13
✎
07:40
|
(55) Так же в запрос можно добавить одно условие и все не подходящие номера выпадут из выборки и ничего не упадет.
Не Номер Подобно "%[^0-9]%" |
|||
57
Лирик
17.04.13
✎
07:42
|
Для числового кода я бы сделал так:
|
|||
58
Лирик
17.04.13
✎
07:42
|
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ | ПробныйСправочник.Код, | ПробныйСправочник.Код + 1 КАК Код1 |ПОМЕСТИТЬ ТаблицаКодов |ИЗ | Справочник.ПробныйСправочник КАК ПробныйСправочник |; | |//////////////////////////////////////////////////////////////////////////////// |ВЫБРАТЬ | МИНИМУМ(ТаблицаКодов1.Код1) КАК Код1 |ИЗ | ТаблицаКодов КАК ТаблицаКодов1 | ЛЕВОЕ СОЕДИНЕНИЕ ТаблицаКодов КАК ТаблицаКодов | ПО ТаблицаКодов1.Код1 = ТаблицаКодов.Код |ГДЕ | ТаблицаКодов.Код ЕСТЬ NULL "; Рез = Запрос.Выполнить().Выбрать(); Рез.Следующий(); ПропущенныйКод = Рез.Код1; |
|||
59
kosts
17.04.13
✎
07:44
|
(58) +1 Можно в одной выборке все сделать.
|
|||
60
IamAlexy
17.04.13
✎
07:49
|
(58) смоделируй работу запроса при пропуске 5ти номеров...
|
|||
61
Лирик
17.04.13
✎
07:52
|
(60) И что?
|
|||
62
cry_san
17.04.13
✎
07:54
|
(58) (60) Все прекрасно работает!!
И мне понравилось ваше простое решение. :) |
|||
63
IamAlexy
17.04.13
✎
07:55
|
(61)
у вас в справочнике заняты номера 1,2,3,10,11,12 сработает запрос ? |
|||
64
cry_san
17.04.13
✎
07:56
|
(63) Да. Выводит 4
|
|||
65
IamAlexy
17.04.13
✎
07:56
|
а хотя да, сработает
|
|||
66
IamAlexy
17.04.13
✎
07:57
|
клевое решение для числовых кодов
|
|||
67
cry_san
17.04.13
✎
07:59
|
Еще один момент. Пользователь создает элемент в справочнике. Номер проставляем один из пустых. Как не дать в этот момент использовать другому пользователю этот же код. Ведь элемент справочника до сих пор ведь не создан.
|
|||
68
kosts
17.04.13
✎
08:00
|
(67) Получай и записывай номер в момент записи в БД. (как в типовых)
|
|||
69
cry_san
17.04.13
✎
08:00
|
(68) А если в этот момент коллизия?
|
|||
70
kosts
17.04.13
✎
08:03
|
(70) Ну не знаю, проверяй существование такого номера и отказ.
|
|||
71
cry_san
17.04.13
✎
08:05
|
(70) Ok!
|
|||
72
cry_san
17.04.13
✎
08:05
|
Все большое СПАСИБО!
|
|||
73
NWsFF
17.04.13
✎
09:29
|
То что было сказано в 9 посте, поняли только к 72. Вах, вах, какие невнимательные.
|
|||
74
Serg_1960
17.04.13
✎
09:58
|
"Не учите меня жить(9), лучше помогите материально(58)"(с)
|
|||
75
Лефмихалыч
17.04.13
✎
10:06
|
(0) вот тебе три номера:
01-вася -петя 02-12 сколько между ними пропущенных? |
|||
76
cry_san
17.04.13
✎
10:26
|
(75) Смотрите ответ тут (66)
|
|||
77
Advan
17.04.13
✎
10:49
|
(58)Класс - правда проблема если код хоть и цифрами, но в формате строковом. Выразить в запросе не переведет строку в число :(
А так был бы мой случай у клиентов - в цикле перебирать долго - думаю придется регистр бацать. |
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |