Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / FoxPro, Visual FoxPro [игнор отключен] [закрыт для гостей] / Помогите таблицы / 25 сообщений из 25, страница 1 из 1
18.06.2009, 11:38
    #36047857
Rickitiki
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите таблицы
Есть 2 одинаковые таблицы. Отличаются количеством записей 1 таблица - 30 000 и 2 таблица - 32 000. Записи содержащиеся в 1 таблице могут отличаться от второй, но не все.
Вопрос: как быстро сопоставить таблицы и добавить 2000-3000 записей, недостающих в первой таблице, из второй таблицы?
Не хочеться тупо перебирать. Долго.
Надеюсь на вашу помощь.
...
Рейтинг: 0 / 0
18.06.2009, 12:14
    #36047972
ВладимирМ
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите таблицы
По каким критериям вы собираетесь определять что такая запись уже есть? По содержимому вообще всех полей или по некоторым ключевым полям?
...
Рейтинг: 0 / 0
18.06.2009, 12:24
    #36048003
GermanGM
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите таблицы
Rickitiki, сформируйте временный "составной" индекс для таблицы с меньшим количеством записей (включающий поля, по которым предполагается сравнение) и затем просканируйте другую. IF !seek(<индексное выражение>) - то добавляете запись. Работы на 5 минут
...
Рейтинг: 0 / 0
19.06.2009, 11:58
    #36050325
Rickitiki
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите таблицы
GermanGM,
Проверка производиться по трем полям.
Хотелось бы не перебором, а каким нибудь select-ом, исключающим повторения.
...
Рейтинг: 0 / 0
23.06.2009, 09:13
    #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
23.06.2009, 14:41
    #36055728
Rickitiki
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите таблицы
alextashk,

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

Уже преобразованная таблица. сократил до 2000 записей.
проверка полей mfg_name, wmi, wmi_ext, year
...
Рейтинг: 0 / 0
23.06.2009, 15:20
    #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
23.06.2009, 15:33
    #36055862
Rickitiki
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите таблицы
alextashk,
спасибо, шас попробую
...
Рейтинг: 0 / 0
23.06.2009, 16:32
    #36056002
Rickitiki
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите таблицы
Rickitiki,
еще раз спасибо, правда очень долго, около 9 мин
...
Рейтинг: 0 / 0
23.06.2009, 16:35
    #36056011
GermanGM
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите таблицы
Rickitiki, не в обиду будь сказано: SCAN работает быстрее... :)
...
Рейтинг: 0 / 0
23.06.2009, 16:52
    #36056060
Rickitiki
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите таблицы
GermanGM,
попробую. может вы правы
...
Рейтинг: 0 / 0
24.06.2009, 13:47
    #36057459
Rickitiki
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите таблицы
GermanGM,
Scan-ом вышло около 11 мин
...
Рейтинг: 0 / 0
24.06.2009, 16:14
    #36057956
tanglir
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите таблицы
RickitikiScan-ом вышло около 11 мин А индекс-то создавали, как рекомендовалось?
...
Рейтинг: 0 / 0
24.06.2009, 17:13
    #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
24.06.2009, 19:29
    #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
24.06.2009, 19:32
    #36058451
tanglir
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите таблицы
Очепятка. Надо не SEEK, а !SEEK, как и советовали выше старшие товарищи.
...
Рейтинг: 0 / 0
24.06.2009, 20:26
    #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
25.06.2009, 11:07
    #36059130
Rickitiki
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите таблицы
tanglir,
Супер, огромное спасибо - 1 секунда, правда программно индекс создать не удается, пишет invalid key lenght, как это исправить.
...
Рейтинг: 0 / 0
25.06.2009, 11:12
    #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
25.06.2009, 14:00
    #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
25.06.2009, 14:07
    #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
25.06.2009, 14:13
    #36059703
tanglir
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите таблицы
проходящий.,
Признаю, забыл и недоглядел. Тогда не получится (проверил). Или индексировать по сумме left-ов от полей, что тоже плохо - могут попасться совпадающие начала.
А может просто поставить другой collate (general, например)? Надо ведь (не)равенство проверять, а не "больше-меньше".
...
Рейтинг: 0 / 0
25.06.2009, 14:45
    #36059810
Rickitiki
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите таблицы
tanglir,
действительно, у меня колейпс был -рашн.
изменил на -машин, все заработало.
еще раз спасибо. Супер
...
Рейтинг: 0 / 0
Форумы / FoxPro, Visual FoxPro [игнор отключен] [закрыт для гостей] / Помогите таблицы / 25 сообщений из 25, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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