powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / FoxPro, Visual FoxPro [игнор отключен] [закрыт для гостей] / Проблемы с SEEK...
19 сообщений из 19, страница 1 из 1
Проблемы с SEEK...
    #35352323
bushuyev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Не пинайте за синтаксис, подскажите, где накосячил...
Есть две DBF таблицы одинаковой структуры. Цель, сопоставить по определенным полям записи...
Вообще ни одной не находит...

CLOSE ALL
CLEAR
SET EXACT off
SET NEAR ON

SELECT 1
USE i
INDEX on CHRTRAN (LOWER (ALLTRIM(typ)+ALLTRIM(koddok)+ALLTRIM(serp)+ALLTRIM(nomp)+dtoc(datareg)+ ALLTRIM(STR(kolakv)) ),' ', '') TO i_nd
SELECT 2

USE i_main

SELECT 2
DO WHILE !EOF()
cargo=''
cargo=CHRTRAN(LOWER(ALLTRIM(i_main.typ)+ALLTRIM(i_main.koddok)+ALLTRIM(i.serp)+ALLTRIM(i_main.nomp)+ALLTRIM(STR(i_main.kolakv)) ),' ', '')

SELECT 1

SEEK cargo
IF FOUND()
...
ELSE
...
ENDIF


SELECT 2
SKIP

ENDDO
CLOSE ALL
CLEAR
....
...
Рейтинг: 0 / 0
Проблемы с SEEK...
    #35352392
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
bushuyevНе пинайте за синтаксис, подскажите, где накосячил...
Есть две DBF таблицы одинаковой структуры. Цель, сопоставить по определенным полям записи...
Вообще ни одной не находит...

А должны? В смысле, точно известно, что есть такие?

Кстати, для размышления, как Вы думаете, будут ли различаться такие строки

"1" + "11" и "11" + "1"

Это по поводу того, как именно Вы строите выражение для сравнения.

Попробуйте более простые решения, например, LOCATE

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
USE i IN  0  alias tab1
USE i_main IN  0  alias tab2

select tab2
SCAN
	select tab1
	LOCATE FOR tab1.typ = tab2.typ AND ;
		tab1.koddok = tab2.koddok AND ;
		tab1.serp = tab2.serp AND ;
		tab1.nomp = tab2.nomp AND ;
		tab1.datareg = tab2.dataReg AND ;
		tab1.kolakv = tab2.kolakv
	IF FOUND("tab1") = .T.
		...
	ELSE
		...
	ENDIF
ENDSCAN

Хотя, разумеется, еще проще было бы сделать это при помощи Select-SQL.
...
Рейтинг: 0 / 0
Проблемы с SEEK...
    #35353073
bushuyev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Такие записи точно есть....
Спасибо за "тему для размышления". Такого в этих таблицах быть не должно, но все-же, надо делать "правильно". Loсate слишком долго работает (в каждой таблице порядка 180 тыс. записей).
...
Рейтинг: 0 / 0
Проблемы с SEEK...
    #35353084
авторПопробуйте более простые решения, например, LOCATE
да, и на порядок медленное


конечно, индекс, строим с разделителями позиций
Код: plaintext
1.
INDEX on LOWER (ALLTRIM(typ)+"_"+ALLTRIM(koddok)+"_"+ALLTRIM(serp)+"_"+ALLTRIM(nomp)+"_"+dtoc(datareg)+"_"+ LTRIM(STR(kolakv))  tag mytagName

попробуйте команду СКЛ языка Select
Код: plaintext
1.
2.
     select t1.* ;
         from t1 ;
             inner join t2 on t1.typ=t2.typ and t1.koddok=t2.koddok and t1.serp=t2.sert and t1.nomp = ....
для включения оптимизации
необходимо построить индексы по всем полям, котор.
присутствуют в условии огранич-я + доп.бинарные по dele() (при set dele off)
inde on koddok tag koddok
inde on serp tag serp
...
inde on dele() tag del binary
...
это сделайте для обеих таблиц
...
Рейтинг: 0 / 0
Проблемы с SEEK...
    #35353542
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
12345вышелзайчикпогулять авторПопробуйте более простые решения, например, LOCATE
да, и на порядок медленное

При наличии тех индексов, которые Вы рекомендуете строить (по каждому полю в отдельности) скорость поиска по LOCATE будет сопоставима со скоростью поиска по SEEK(), поскольку команда LOCATE также использует Rushmore-оптимизацию. Однако в отличие от SEEK может одновременно использовать несколько индексов.

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

1. Одно из полей внутри себя может содержать использованный символ-разделитель.
2. Время построения такого индекса "съест" весь выигрыш от производительности при его использовании. И еще не факт, что поиск вместе с построением индекса окажется быстрее, чем поиск без использования индекса вообще

Это значит, что использование таких составных индексов лучше избегать. По возможности, выражение индекса должно быть максимально простым. В идеале, просто имя соответствующего поля.

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

12345вышелзайчикпогулятьпопробуйте команду СКЛ языка Select
INNER JOIN в данном случае использовать не корректно, поскольку из условия задачи не ясно, будут ли совпадения в единственном числе. Поэтому надо использовать IN или EXISTS()

Код: plaintext
1.
2.
3.
4.
select t1.* ;
from t1 ;
WHERE EXISTS(SELECT 'x' ;
                  FROM t2 ;
                  WHERE t1.typ=t2.typ and t1.koddok=t2.koddok and t1.serp=t2.sert and t1.nomp = ....)

12345вышелзайчикпогулять+ доп.бинарные по dele() (при set dele off)
Необходимость использования индекса по Deleted() - вопрос спорный и не однозначный. В подобных задачах эту тему лучше не поднимать.
...
Рейтинг: 0 / 0
Проблемы с SEEK...
    #35353590
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
bushuyevВообще ни одной не находит...
SELECT 1
USE i
INDEX on CHRTRAN(...,' ', '') TO i_nd

А не находит он именно из-за использования ChrTran().

Дело в том, что в среде FoxPro все индексы имеют фиксированную длину ключа. Это значит, что, если выражение индекса для первой записи сформирует длину ключа, скажем в 10 символов, то и для всех остальных ключей длина также окажется равной 10 символам. Даже если выражение вернет больше символов. "Лишние" символы будут просто отброшены.

Как правило, FoxPro сам, автоматически, дополняет длину выражения до некоторой фиксированной длины при использовании простых функций. Например, если выражение ключа написать так:

AllTrim(Field1)

то FoxPro, конечно, отбросит ведущие и концевые пробелы, но затем сам, автоматически, добавит концевые пробелы до длины поля Field1.

Однако в сложных функциях вроде ChrTran() такого автоматического дополнения не происходит. В этом случае надо озаботиться ручным добавлением пробелов до некоторой фиксированной длины, например, с использованием функции PADR()

Код: plaintext
PADR(ChrTran(..., " ", ""),  100 )

Кстати, если Вы используете ChrTran(), то нет смысла использовать AllTrim(). И наоборот. В данном случае - одна из этих функций делает то же самое, что и другая. Разумеется, если не может оказаться пробела внутри значения поля. Вы просто дублируете одну и ту же операцию.
...
Рейтинг: 0 / 0
Проблемы с SEEK...
    #35353639
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
С индексом можно не заморачиваться на ALLTRIM если длинных полей внутрь индексного выражения не попадает. Ключ переменной длины ничего хорошего не даст.
Код: plaintext
1.
USE i
INDEX on LOWER(typ+koddok+serp+nomp)+dtoc(datareg)+STR(kolakv,  10 ) TO i_nd COMPACT
При 180 тыс. записей индекс даст хорошую производительность, тем более что при SELECT оптимизатор сам временный индекс будет делать при его отсутствии.

А дальше можно по SET RELATION связать и за один SCAN обработать. Примерно так:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
sele  0 
use i_main
set rela to LOWER(typ+koddok+serp+nomp)+dtoc(datareg)+STR(kolakv,  10 ) into i
scan
      if !empty(i.typ+i.koddok+i.serp+i.nomp) and !empty(i.datareg) and !empty(i.kolakv)
         ? 'Совпало: ', typ+koddok+serp+nomp
      else
         ? 'Не совпало: ', typ+koddok+serp+nomp
      endif
endscan
set rela to
...
Рейтинг: 0 / 0
Проблемы с SEEK...
    #35353653
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Тут поторопился:
Код: plaintext
if !empty(i.typ+i.koddok+i.serp+i.nomp) and !empty(i.datareg) and !empty(i.kolakv)
Лучше так проверять:
Код: plaintext
if LOWER(i.typ+i.koddok+i.serp+i.nomp)+dtoc(i.datareg)+STR(i.kolakv,  10 ) = LOWER(i_main.typ+i_main.koddok+i_main.serp+i_main.nomp)+dtoc(i_main.datareg)+STR(i_main.kolakv,  10 )
...
Рейтинг: 0 / 0
Проблемы с SEEK...
    #35353672
bushuyev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Спасибо всем, что не поленились так подробно и по делу ответить!!!
...
Рейтинг: 0 / 0
Проблемы с SEEK...
    #35353688
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima TА дальше можно по SET RELATION связать и за один SCAN обработать.
Если настроен RELATION, то проверять надо на EOF() подчиненной таблицы. Ведь если значения нет, то мы просто попадем на фиктивную запись подчиненной таблицы. А проверять на EMPTY() - некорректно, ведь запись действительно может быть пустой.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
sele  0 
use i_main
set rela to LOWER(typ+koddok+serp+nomp)+dtoc(datareg)+STR(kolakv,  10 ) into i
scan
      if !EOF("i")
         ? 'Совпало: ', typ+koddok+serp+nomp
      else
         ? 'Не совпало: ', typ+koddok+serp+nomp
      endif
endscan
set rela to
...
Рейтинг: 0 / 0
Проблемы с SEEK...
    #35353754
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ВладимирМА проверять на EMPTY() - некорректно, ведь запись действительно может быть пустой.
Это я понял когда запостил и поправился (см. выше). Привычка - обычно у меня по одному всегда непустому полю связка, пустое значит отсутствует.
Про EOF() согласен - так заметно короче.
...
Рейтинг: 0 / 0
Проблемы с SEEK...
    #35353906
XAndy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Если надо действительно быстро, на порядки быстрее, то можно вести контрольные суммы записей (при каждом изменении данных обновлять crc). Cравнивать уже только короткое поле crc. В фоксе (не помню с какой версии) для этого даже есть специальная функция SYS(2017) , в которой список полей для расчета crc32 можно ограничить указанными.

Если поддерживать контрольные суммы невозможно, то можно их рассчитывать непосредственно перед сравнением. Недостаточно crc32 - заменить на md5. По крайней мере это будет человеческое решение, в отличие от безумных индексов (не забываем и про ограничение на длину индексируемого выражения!)
...
Рейтинг: 0 / 0
Проблемы с SEEK...
    #35353987
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
XAndyЕсли надо действительно быстро, на порядки быстрее, то можно вести контрольные суммы записей (при каждом изменении данных обновлять crc). Cравнивать уже только короткое поле crc. В фоксе (не помню с какой версии) для этого даже есть специальная функция SYS(2017) , в которой список полей для расчета crc32 можно ограничить указанными.

Если поддерживать контрольные суммы невозможно, то можно их рассчитывать непосредственно перед сравнением. Недостаточно crc32 - заменить на md5. По крайней мере это будет человеческое решение, в отличие от безумных индексов (не забываем и про ограничение на длину индексируемого выражения!)

Где гарантия что SYS(2007), CRC32 и даже MD5 дадут уникальные значения для каждой записи? Это хэш, который может быть одинаковым для двух разных наборов данных, вероятность очень маленькая, но всеже она есть.
Закладывая в код проверку на задвоение хэша в добавок к его расчету для каждой записи получим далеко не самое быстрое решение, и коду с проверками на задвоение хэша придется пописать немало.

Индекс не безумный, ограничение 240 байт на длину ключа.
...
Рейтинг: 0 / 0
Проблемы с SEEK...
    #35354181
XAndy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Dima TГде гарантия что SYS(2007), CRC32 и даже MD5 дадут уникальные значения для каждой записи? Это хэш
Гарантий нет, и я в курсе, что такое хэш ;)
Однако, Вы лично оценивали вероятность повторения? Прежде чем кидаться громкими фразами про гарантии и т.п.? Так вот сравните вероятность повторения md5 c, к примеру, попаданием молнии или метеорита лично в Вас :). Как думаете, вероятность чего выше, совпадения двух md5 или безвозвратного падения вашего HDD?

Dima TЗакладывая в код проверку на задвоение хэша
Пишется код для РВСН?

Dima TИндекс не безумный, ограничение 240 байт на длину ключа.
Безумный. Я такие индексы так называю ;)
...
Рейтинг: 0 / 0
Проблемы с SEEK...
    #35354285
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
XAndyГарантий нет, и я в курсе, что такое хэш ;)
Однако, Вы лично оценивали вероятность повторения?
SYS(2007) - 100% вероятность. Он от 0 до 65535 возвращает. При 180 тыс. записей обязательно повторится. Встроенного CRC32 или MD5 в фоксе нет, есть правда реализации третьими средствами.

Не думаю что провести расчет CRC32 или MD5 для каждой записи (даже предположив что они всегда уникальны), потом проиндексировать и сравнить будет:
XAndyна порядки быстрее
Возможно чуть быстрее, и то сильно в этом сомневаюсь.

XAndy Dima TЗакладывая в код проверку на задвоение хэша
Пишется код для РВСН?
Потеря 1 копейки для бухгалтерии не менее опасна ;)
...
Рейтинг: 0 / 0
Проблемы с SEEK...
    #35354803
XAndy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Dima TSYS(2007) - 100% вероятность. Он от 0 до 65535 возвращает
crc16 я не предлагал

Dima TВстроенного CRC32 или MD5 в фоксе нет, есть правда реализации третьими средствами.
CRC32 есть и в sys(2007), и в sys(2017) ;), md5 - таки да, dll-ку надо, в чем не вижу проблемы.
Кстати, функция sys(2017) - штатное средство для решения поставленной автором задачи, которое фокстим добавила по просьбам разработчиков

Dima TНе думаю что провести расчет CRC32 или MD5 для каждой записи (даже предположив что они всегда уникальны), потом проиндексировать и сравнить будет "на порядки быстрее"
Если расчет вести во время ввода/изменения исходных данных , то сравнение будет именно на порядки быстрее. Зависит от специфики задачи автора, может и подойдет ему такой вариант.

Dima TЗакладывая в код проверку на задвоение хэша
XAndyПишется код для РВСН?
Dima TПотеря 1 копейки для бухгалтерии не менее опасна ;)
Наши бухи могут за копейку удавить, но миллион "потерять" :)
...
Рейтинг: 0 / 0
Проблемы с SEEK...
    #35355507
Galyamov Rinat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
>
> Dima T
> Закладывая в код проверку на задвоение хэша
>
> XAndy
> Пишется код для РВСН?

В данном случае все таки есть смысл просчитать хэш. При анализе
Вытаскивать записи с совпашим хэшем, потом сравнивать значение самих полей.

Думаю будет заметно быстрее, прозрачнее, тем более что расчитанный хэш можно
хранить в доп поле в той же записи, что и данные.


А ответственность за корректность содержимого этого поля повешать на правила
БД.

2 DimaT, знаю, что ты контейнеры не любишь, но не у всех задача настолько
распределенная, как у тебя. ;)


Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
Проблемы с SEEK...
    #35355740
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
XAndy Dima TSYS(2007) - 100% вероятность. Он от 0 до 65535 возвращает
crc16 я не предлагал

В VFP6 смотрел, там только CRC16. В 9-ке CRC32 появилось. Будем знать :)

HELP VFP6SYS(2017) - Display Startup Screen
Included for backward compatibility. Use CREATE FORM instead.


Задвоения CRC32 тоже вполне вероятны. Написал небольшую программку для поиска задвоений. Вот результаты:
Код: plaintext
1.
2.
3.
4.
? sys( 2017 , [ 3680173401 ],  0 ,  1 )=sys( 2017 , [ 2766565050 ],  0 ,  1 )
? sys( 2017 , [ 1394610755 ],  0 ,  1 )=sys( 2017 , [ 703363090  ],  0 ,  1 )
? sys( 2017 , [ 515960556  ],  0 ,  1 )=sys( 2017 , [ 3348877065 ],  0 ,  1 )
? sys( 2017 , [ 650017806  ],  0 ,  1 )=sys( 2017 , [ 2814937763 ],  0 ,  1 )
? sys( 2017 , [ 515960556  ],  0 ,  1 )=sys( 2017 , [ 3348877065 ],  0 ,  1 )
Задвоение стабильно находится в наборе из 100-150 тыс. значений. Что в принципе логично, т.к. тут алгоритм CRC не по назначению используется, он разрабатывался для контроля целостности двоичных данных передаваемых по ненадежным каналам, т.е. где по дороге пару-тройку 1 в 0 и наоборот может переключиться. Например при помехах в телефонной линии между двумя модемами.

Остается MD5, он для подобных целей и делался изначально, с ним уникальность наиболее вероятная. Программка молотит, 15 млн. разных записей имеют разные MD5.
XAndyЗависит от специфики задачи автора, может и подойдет ему такой вариант.
Тут полностью согласен. Размер поля под MD5 32 байта, что не так уж и мало. Стоит оно того или нет, надо решать индивидуально для каждой конкретной задачи.

Может быть у автора две копии таблицы от разного времени, тогда достаточно заранее Id сделать и считать никаких хэшей не надо.
...
Рейтинг: 0 / 0
Проблемы с SEEK...
    #35365671
LR2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
LR2
Гость
XAndyТак вот сравните вероятность повторения md5
Можно выписать и точную формулу, но она сложная и непонятная, а если прикинуть, то вероятность того, что MD5 хеш совпадет у каких-либо двух записей в таблице с миллиардом записей не превышает одной миллиардной (плюс-минус один-два порядка)
...
Рейтинг: 0 / 0
19 сообщений из 19, страница 1 из 1
Форумы / FoxPro, Visual FoxPro [игнор отключен] [закрыт для гостей] / Проблемы с SEEK...
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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