powered by simpleCommunicator - 2.0.55     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / FoxPro, Visual FoxPro [игнор отключен] [закрыт для гостей] / Помогите таблицы
25 сообщений из 25, страница 1 из 1
Помогите таблицы
    #36047857
Rickitiki
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Есть 2 одинаковые таблицы. Отличаются количеством записей 1 таблица - 30 000 и 2 таблица - 32 000. Записи содержащиеся в 1 таблице могут отличаться от второй, но не все.
Вопрос: как быстро сопоставить таблицы и добавить 2000-3000 записей, недостающих в первой таблице, из второй таблицы?
Не хочеться тупо перебирать. Долго.
Надеюсь на вашу помощь.
...
Рейтинг: 0 / 0
Помогите таблицы
    #36047972
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
По каким критериям вы собираетесь определять что такая запись уже есть? По содержимому вообще всех полей или по некоторым ключевым полям?
...
Рейтинг: 0 / 0
Помогите таблицы
    #36048003
GermanGM
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Rickitiki, сформируйте временный "составной" индекс для таблицы с меньшим количеством записей (включающий поля, по которым предполагается сравнение) и затем просканируйте другую. IF !seek(<индексное выражение>) - то добавляете запись. Работы на 5 минут
...
Рейтинг: 0 / 0
Помогите таблицы
    #36050325
Rickitiki
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
GermanGM,
Проверка производиться по трем полям.
Хотелось бы не перебором, а каким нибудь select-ом, исключающим повторения.
...
Рейтинг: 0 / 0
Помогите таблицы
    #36054944
alextashk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Rickitiki,

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
	SELECT table1.id, table2.field1, table2.field2, table2.field3,  1  AS iType;
		FROM table1 ;
		INNER JOIN table2 ;
			ON  table1.id = table2.id;
		WHERE  table1.field1 <> table2.field1;
			OR  table1.field2 <> table2.field2;
			OR  table1.field3 <> table2.field3;
	UNION;  
		SELECT table1.*,  2  AS iType ;
		FROM table1;
		WHERE table1.id NOT IN (SELECT table2.id FROM table2);
	UNION;
		SELECT table2.id, table2.field1, table2.field2, table2.field3,  3  AS iType ;
		FROM table2;
		WHERE table2.id NOT IN (SELECT table1.id FROM table1);
	INTO CURSOR list 

Собственно нужен уникальный ID в обеих одинаковых по структуре таблицах
iType = 1 - существующие и в table1 и в table2, но изменившиеся
iType = 2 - существующие в table1 но не в table2
iType = 3 - существующие в table2 но не в table1
...
Рейтинг: 0 / 0
Помогите таблицы
    #36055728
Rickitiki
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
alextashk,

спасибо, но вторую таблицу беру с инета (с официально сайта), в аксесе, перегоняю в фокс. обновление таблицы в нете, каждый месяц. первая таблица добавляется своими записями тоже. Уникальный ключ можно сделать первой таблице, а второй?
может как-то через select DISTINCT, но у меня не получается.
...
Рейтинг: 0 / 0
Помогите таблицы
    #36055738
alextashk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Rickitiki,
Всегда есть поля, или группа полей, которые можно использовать как ID строки.
Выложи, что получаешь из Interneta
...
Рейтинг: 0 / 0
Помогите таблицы
    #36055793
Rickitiki
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
alextashk,

Уже преобразованная таблица. сократил до 2000 записей.
проверка полей mfg_name, wmi, wmi_ext, year
...
Рейтинг: 0 / 0
Помогите таблицы
    #36055829
alextashk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Rickitiki,

в этом случае, возможно отслеживать только добавление и удаление

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
	SELECT wmi1.*,  2  AS iType ;
		FROM wmi1;
		WHERE wmi1.mfg_name+wmi1.wmi+wmi1.wmi_ext+wmi1.year NOT IN (SELECT wmi2.mfg_name+wmi2.wmi+wmi2.wmi_ext+wmi2.year FROM wmi2);
	UNION;
		SELECT wmi2.*,  3  AS iType ;
		FROM wmi2;
		WHERE wmi2.mfg_name+wmi2.wmi+wmi2.wmi_ext+wmi2.year NOT IN (SELECT wmi1.mfg_name+wmi1.wmi+wmi1.wmi_ext+wmi1.year FROM wmi1);
	INTO CURSOR list 

mfg_name+wmi+wmi_ext+year является уникальным ID, поскольку выборка SELECT mfg_name+wmi+wmi_ext+year, COUNT(*) FROM wmi1 из 2000 записей дала 2000 записей
iType = 2 - существующие в table1 но не в table2
iType = 3 - существующие в table2 но не в table1
...
Рейтинг: 0 / 0
Помогите таблицы
    #36055862
Rickitiki
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
alextashk,
спасибо, шас попробую
...
Рейтинг: 0 / 0
Помогите таблицы
    #36056002
Rickitiki
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Rickitiki,
еще раз спасибо, правда очень долго, около 9 мин
...
Рейтинг: 0 / 0
Помогите таблицы
    #36056011
GermanGM
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Rickitiki, не в обиду будь сказано: SCAN работает быстрее... :)
...
Рейтинг: 0 / 0
Помогите таблицы
    #36056060
Rickitiki
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
GermanGM,
попробую. может вы правы
...
Рейтинг: 0 / 0
Помогите таблицы
    #36057459
Rickitiki
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
GermanGM,
Scan-ом вышло около 11 мин
...
Рейтинг: 0 / 0
Помогите таблицы
    #36057956
tanglir
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
RickitikiScan-ом вышло около 11 мин А индекс-то создавали, как рекомендовалось?
...
Рейтинг: 0 / 0
Помогите таблицы
    #36058150
Rickitiki
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
tanglir,
вот пример кода
может че не так, поправте пожалуйста

Код: 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.
CREATE CURSOR temp_wmi(mfg_name C( 200 ), wmi C( 3 ), wmi_ext C( 3 ), country C( 100 ), year C( 10 ))
? DATETIME()
SELECT wmi1
GO top
SCAN
	IF RECNO() >  999 
		IF MOD(RECNO(),  1000 ) =  0 
			? RECNO()
		ENDIF 
	ENDIF 
	
	SELECT wmi
	LOCATE FOR UPPER(ALLTRIM(wmi.wmi)) = UPPER(ALLTRIM(wmi1.wmi)) AND;
				UPPER(ALLTRIM(wmi.wmi_ext)) = UPPER(ALLTRIM(wmi1.wmi_ext)) and;
				UPPER(ALLTRIM(wmi.mfg_name)) = UPPER(ALLTRIM(wmi1.mfg_name))
	IF FOUND()
		SELECT wmi1
	ELSE
		SELECT wmi1
		INSERT INTO temp_wmi(mfg_name, wmi, wmi_ext, country, year) VALUES(ALLTRIM(wmi1.mfg_name),;
					ALLTRIM(wmi1.wmi), ALLTRIM(wmi1.wmi_ext), ALLTRIM(wmi1.country),  ALLTRIM(wmi1.year))
	ENDIF 
	
ENDSCAN
? DATETIME()
...
Рейтинг: 0 / 0
Помогите таблицы
    #36058447
tanglir
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: plaintext
LOCATE FOR
GermanGMRickitiki, сформируйте временный "составной" индекс для таблицы с меньшим количеством записей (включающий поля, по которым предполагается сравнение) и затем просканируйте другую. IF !seek(<индексное выражение>) - то добавляете запись. Работы на 5 минут
Почитайте про индексы.
ЗЫ. Ну как-то так
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
select wmi
index on UPPER(ALLTRIM(wmi))+UPPER(ALLTRIM(wmi_ext))+UPPER(ALLTRIM(wmi_name)) tag myidx1 additive
set order to myidx1
<...>
scan
<...>
if seek(UPPER(ALLTRIM(wmi1.wmi)) +UPPER(ALLTRIM(wmi1.wmi_ext)) +UPPER(ALLTRIM(wmi1.mfg_name))
*select,insert,чего надо
endif
endscan
Кста, а зачем в обоих ветках if-endif стоит select wmi1 ?
...
Рейтинг: 0 / 0
Помогите таблицы
    #36058451
tanglir
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Очепятка. Надо не SEEK, а !SEEK, как и советовали выше старшие товарищи.
...
Рейтинг: 0 / 0
Помогите таблицы
    #36058504
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Еще один вариант "до кучи"


Код: 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.
28.
29.
30.
31.
32.
33.
* Временный курсор
CREATE CURSOR temp_wmi(mfg_name C( 200 ), wmi C( 3 ), wmi_ext C( 3 ), country C( 100 ), year C( 10 ), tabNum N( 1 ))

* Добавляем ВСЕ записи первой таблицы
APPEND FROM wmi1

* И устанавливаем признак того, что записи добавлены из первой таблицы
REPLACE ALL tabNum WITH  1 

* Добавляем ВСЕ записи второй таблицы
APPEND FROM wmi2

* И устанавливаем признак того, что записи добавлены из второй таблицы
REPLACE tabNum WITH  2  FOR Recno() > Reccount("wmi1")

* Ищем в получившемся курсоре уникальные (не повторяющиеся) значения

SELECT ;
	mfg_name, ;
	wmi, ;
	wmi_ext, ;
	country, ;
	year, ; 
	max(tabNum) as tabNum ;
FROM temp_wmi ;
INTO CURSOR curUniq ;
GROUP BY ;
	mfg_name, ;
	wmi, ;
	wmi_ext, ;
	country, ;
	year ; 
HAVING Count(distinct tabNum) =  1 

В результате, в получившемся курсоре curUniq будут только уникальные записи, которые не повторяются. А значение поля tabNum будет содержать идентификатор таблицы, в которой эта запись находится.

Условие отбора HAVING Count(distinct tabNum) = 1 говорит о том, что если дубль есть в рамках одной таблицы, то обе эти записи должны попасть в результирующую выборку.

Если стоит задача исключить еще дубли в рамках одной таблицы (взять только одно значение дубля), то задача сильно усложняется.

Если надо оставить только уникальные записи из второй таблицы, то условие можно дополнить так

Код: plaintext
HAVING Count(distinct tabNum) =  1  AND max(tabNum) =  2 

PS: Кстати, думаю ваш пример со SCAN работал в два раза дольше по той причине, что вы при поиске оборачивали поля в UPPER(ALLTRIM()). Или в Select-SQL вы делали то же самое?
...
Рейтинг: 0 / 0
Помогите таблицы
    #36059130
Rickitiki
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
tanglir,
Супер, огромное спасибо - 1 секунда, правда программно индекс создать не удается, пишет invalid key lenght, как это исправить.
...
Рейтинг: 0 / 0
Помогите таблицы
    #36059148
Rickitiki
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
tanglir
Код: plaintext
LOCATE FOR
GermanGMRickitiki, сформируйте временный "составной" индекс для таблицы с меньшим количеством записей (включающий поля, по которым предполагается сравнение) и затем просканируйте другую. IF !seek(<индексное выражение>) - то добавляете запись. Работы на 5 минут
Почитайте про индексы.
ЗЫ. Ну как-то так
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
select wmi
index on UPPER(ALLTRIM(wmi))+UPPER(ALLTRIM(wmi_ext))+UPPER(ALLTRIM(wmi_name)) tag myidx1 additive
set order to myidx1
<...>
scan
<...>
if seek(UPPER(ALLTRIM(wmi1.wmi)) +UPPER(ALLTRIM(wmi1.wmi_ext)) +UPPER(ALLTRIM(wmi1.mfg_name))
*select,insert,чего надо
endif
endscan
Кста, а зачем в обоих ветках if-endif стоит select wmi1 ?

Подскажите где почитать про индексы?
...
Рейтинг: 0 / 0
Помогите таблицы
    #36059652
tanglir
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
VFP9 HelpInvalid key length (Error 112)
If you created an index key that exceeds the following limits, create a shorter index key.
The length of an index key for an index or compiled index (.idx) must be between 1 and 100 characters. The length for a compound index (.cdx) must between 1 and 240 characters.
<...>
When Visual FoxPro creates an index, it evaluates fields in the first record in the table.
В хелпе про индексы основное написано.
Фокс пишет, что индексное выражение получается слишком длинным (более 240 символов). Странно, вот так (вбил максимально длинные значения в поля)
Код: plaintext
1.
2.
CREATE TABLE "D:\wmi.dbf" (wmi_name C( 200 ), wmi C( 3 ), wmi_ext C( 3 ), country C( 100 ), year C( 10 ))
INSERT INTO wmi VALUES ( REPLICATE('q', 200 ), REPLICATE('q', 3 ), REPLICATE('q', 3 ), REPLICATE('q', 100 ), REPLICATE('q', 10 ))
index on UPPER(ALLTRIM(wmi))+UPPER(ALLTRIM(wmi_ext))+UPPER(ALLTRIM(wmi_name)) tag myidx1 additive
индекс создался и Фокс не ругался. Какая у Вас суммарная длина полей wmi,wmi_ext,wmi_name?
...
Рейтинг: 0 / 0
Помогите таблицы
    #36059680
tanglirVFP9 HelpInvalid key length (Error 112)
If you created an index key that exceeds the following limits, create a shorter index key.
The length of an index key for an index or compiled index (.idx) must be between 1 and 100 characters. The length for a compound index (.cdx) must between 1 and 240 characters.
<...>
When Visual FoxPro creates an index, it evaluates fields in the first record in the table.
F почему важный следующий абзац не процитировали?
Код: plaintext
With some collating sequences, or when using double-byte character set (DBCS) characters, each character in the index expression uses two characters in the index key. In these cases, the length of the index expression is limited to 50 or 120 characters, respectively.
К set collation to russian это относится самым прямым образом.
...
Рейтинг: 0 / 0
Помогите таблицы
    #36059703
tanglir
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
проходящий.,
Признаю, забыл и недоглядел. Тогда не получится (проверил). Или индексировать по сумме left-ов от полей, что тоже плохо - могут попасться совпадающие начала.
А может просто поставить другой collate (general, например)? Надо ведь (не)равенство проверять, а не "больше-меньше".
...
Рейтинг: 0 / 0
Помогите таблицы
    #36059810
Rickitiki
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
tanglir,
действительно, у меня колейпс был -рашн.
изменил на -машин, все заработало.
еще раз спасибо. Супер
...
Рейтинг: 0 / 0
25 сообщений из 25, страница 1 из 1
Форумы / FoxPro, Visual FoxPro [игнор отключен] [закрыт для гостей] / Помогите таблицы
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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