powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / FoxPro, Visual FoxPro [игнор отключен] [закрыт для гостей] / Свободные номера через SQL-запрос
13 сообщений из 13, страница 1 из 1
Свободные номера через SQL-запрос
    #33255498
kms_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Доброго всем времени суток!

Ребяты есть такой вопросик: в таблице oss.dbf хранятся объекты с инвентарными номерами скажем от 100000 до 999999, вводим новый объект - ему надо присвоить инвентарный номер, которого в таблице oss.dbf нет.
Как сформировать SQL-запрос, чтобы он выдал все свободные номера от 100000 до 999999, которых нет в oss.dbf

Вариант когда создается курсор с одним полем, содержащим номера от 100000 до 999999, а потом делается SQL-запрос используя связку NOT IN не совсем подходит....

Заранее благодарен!
...
Рейтинг: 0 / 0
Свободные номера через SQL-запрос
    #33255551
Фотография Hel!Riser
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
имхо иначе никак. курсор значений пусть существует фсегда. А если в результате такого запроса те не нравица слишком большое количество записеq, то пользуй конструкцию типа SELECT MIN(Value) FROM AllValues WHERE NOT IN () тогда фсегда будет возвращена тока одно свободное число
...
Рейтинг: 0 / 0
Свободные номера через SQL-запрос
    #33255563
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ты уж определись, что именно тебе нужно:

Узнать ВСЕ "дыры" в нумерации

Узнать ПЕРВУЮ (одну) "дыру" в нумерации

В любом случае, без дополнительной таблицы это займет достаточно много времени. Поиск первой попавшейся примерно так:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
LOCAL lnI
select MyTab
SET ORDER TO TabNum
GO TOP
lnI =  1 
SCAN WHILE m.lnI = MyTab.TabNum
	m.lnI = m.lnI+ 1 
ENDSCAN
?"Первая дыра в нумерации ", m.lnI

Здесь TabNum - это поле с табельным номером. По нему построен индекс. Если "дыра" в начале нумерации, то поиск пройдет быстро, а если в конце или вообще нет дыр, то очень медленно.

Хотя, можно предварительно оценить, есть ли дыры вообще

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
SELECT COUNT(*) as kol, MAX(TabNum) as MaxNum ;
FROM MyTab ;
INTO CURSOR curExistHole NOFILTER

IF curExistHole.kol <> curExistHole.MaxNum
	* Есть дыры в нумерации
ENDIF

Если надо узнать ВСЕ "дыры", то несколько сложнее

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
CREATE CURSOR NoTabNum (TabNum N( 6 ))
LOCAL lnI, lnJ
select MyTab
SET ORDER TO TabNum
GO TOP
lnI =  1 
SCAN 
	IF m.lnI <> MyTab.TabNum
		FOR m.lnJ=m.lnI TO MyTab.TabNum- 1 
			INSERT INTO NoTabNum VALUES (m.lnJ)
		ENDFOR
		m.lnI = MyTab.TabNum
	ENDIF
	m.lnI = m.lnI+ 1 
ENDSCAN
* Тут можно добавить все значения от MAX(TabNum) 
* до максимально допустимого в данном поле

* Результат выборки
select NoTabNum
BROWSE NOWAIT
...
Рейтинг: 0 / 0
Свободные номера через SQL-запрос
    #33255564
Komissar
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
если бы oss.dbf была отсортирована... тогда бы подошло
Код: plaintext
1.
2.
LOCATE FOR <инв_номер>#recno()+ 99999 
<new_номер>=<инв_номер>- 1 
INSERT BEFORE ...
но это некрасиво...
...
Рейтинг: 0 / 0
Свободные номера через SQL-запрос
    #33255572
kms_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Ясненько.... тогда уж лучше первый вариант, хотя я очень надеялся на что-то более оригинальное.

Спасибо, Hel!Riser.
...
Рейтинг: 0 / 0
Свободные номера через SQL-запрос
    #33255573
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Тут проще и быстрее без запроса
упорядочиваешь по номеру
идешь по таблице и считашь счетчиком параллельно. Как счетчик не совпал. Значит нашел.

примерно так
Код: plaintext
1.
2.
3.
4.
5.
6.
lnInvNo =  1000000 
sele my_dbf
set order to nInvNo
scan for lnInvNo = my_dbf.nInvNo
      lnInvNo = lnInvNo +  1 
endscan
...
Рейтинг: 0 / 0
Свободные номера через SQL-запрос
    #33255591
kms_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Ух, ребяты, спасибо... столько сразу ответов, но у меня именно перебор и используется, а я хотел что-то побыстрее...

Мне понравился вариант, который предложил Komissar, но, к сожалению, он не подходит так как в таблице инвентраные номера не целые, а имеют дробную часть...

Все равно всем спасибо. Наверное создам табличку с одним полем и со всеми доступными номерами и пусть валяется себе на диске, а когда необходимо буду выбирать из нее те номера, которых нет в oss.dbf одним запросом и быстро и просто!
...
Рейтинг: 0 / 0
Свободные номера через SQL-запрос
    #33255664
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вариант, предложенный Komissar не подходит при любом раскладе. Дробные числа можно умножать, например, на 1000, чтобы они стали целыми. Проблема не в этом.

Recno() не учитывает записи помеченные как удаленные. Т.е. их вроде уже как нет, но данный алгоритм предполагает, что есть.

Команда INSERT BEFOR требует эксклюзивного доступа к таблице. Накладывает ряд ограничений на саму таблицу. В VFP оставлена для обратной совместимости. Не стоит использовать подобные команды без крайней необходимости.
...
Рейтинг: 0 / 0
Свободные номера через SQL-запрос
    #33255734
Komissar
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ВладимирМВариант, предложенный Komissar не подходит при любом раскладе...
1. а зачем удалять инвентарные номера??? куда они деваются чтоб их надо было удалять???
2. ну я и сказал что "некрасиво"!
...
Рейтинг: 0 / 0
Свободные номера через SQL-запрос
    #33255745
PaulWist
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
И мои несколько копеек

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
* таблица с инв номерами
CREATE CURSOR test (id i)
SELECT test 
INDEX ON ID TAG ID
* занесем тройку штук
INSERT INTO test (id) VALUES ( 1 )
INSERT INTO test (id) VALUES ( 3 )
INSERT INTO test (id) VALUES ( 10 )
* курсор с отсутствующими номерами
CREATE CURSOR NotInTest (id i)

SELECT NotID(ID) FROM Test INTO CURSOR ttt
* смотрим отсутствующие номера, прада первая запись задвоилась
SELECT NotInTest
BROWSE 
* ф-ия собирает все отсутствующие номера
FUNCTION NotID
LPARAMETERS ID
* m.ID <  10  верхний предел, надо так же поставить нижний предел
* что бы начать с него нумерацию
IF m.ID <  10  AND INDEXSEEK(m.id, .f., 'test', 'ID') 
	m.ID = m.ID +  1 
	DO WHILE NOT INDEXSEEK(m.id, .f., 'test', 'ID')
		INSERT INTO NotInTest (ID) VALUES (m.ID)
		m.ID = m.ID +  1 
	ENDDO 
ENDIF 
ENDFUNC 
...
Рейтинг: 0 / 0
Свободные номера через SQL-запрос
    #33255808
kms_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ВладимирМ, по поводу примера Kommisar'a вы, конечно, правы, но мне и не нужна была команда INSERT BEFORE просто мне понравился вариант нахождения первого свободного номера...

PaulWist, вам спасибо за пример, но видимо из-за версии фокса у меня не идет функция INDEXSEEK.
...
Рейтинг: 0 / 0
Свободные номера через SQL-запрос
    #33257582
Igor Korolyov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Hi kms_!

> видимо из-за версии фокса у меня не идет функция INDEXSEEK.

Какая же у тебя версия то :(

Вообще найти "дырки" в нумерации можно и сравнительно простым SQL запросом -
например таким:

SELECT t1.nID + 1 FROM test t1 WHERE t1.nID NOT IN (SELECT t2.nID - 1 FROM
test t2)

и/или таким:

SELECT t1.nID - 1 FROM test t1 WHERE t1.nID NOT IN (SELECT t2.nID + 1 FROM
test t2)

Конечно это даст НЕ ВСЕ дырки, а лишь первые (или соответственно последние)
из пропущенных интервалов - ну т.е. если пропущены номера с 5 по 20, то
первый запрос вернёт 5, а второй - 20 "промежуточные" значения возвращены не
будут. Если пропущено всего одно значение (т.е. есть всё кроме # 5), то
конечно в обоих случаях будет возвращено именно оно - это своеобразный
интервал содержащий всего 1 число.

Posted via ActualForum NNTP Server 1.3
...
Рейтинг: 0 / 0
Свободные номера через SQL-запрос
    #33260097
Фотография MaestroEv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
У меня работает такой вариант...
*********************************
SELECT NOMER NOFILTER FROM NOMERIN ORDER BY 1 INTO CURS _NOMER_
M.DYRKA=_TALLY+1
IF M.DYRKA-1<_NOMER_.NOMER &&& ЕСТЬ ДЫРКИ
INDEX ON NOMER TAG NOMER FOR NOMER-RECNO()>0
****************
GO TOP
M.DYRKA=IIF(_NOMER_.NOMER>0,_NOMER_.NOMER-1,M.DYRKA)
ENDIF
*********************************
...
Рейтинг: 0 / 0
13 сообщений из 13, страница 1 из 1
Форумы / FoxPro, Visual FoxPro [игнор отключен] [закрыт для гостей] / Свободные номера через SQL-запрос
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]