powered by simpleCommunicator - 2.0.56     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / FoxPro, Visual FoxPro [игнор отключен] [закрыт для гостей] / Возможна ли оптимизация такого кода...
9 сообщений из 9, страница 1 из 1
Возможна ли оптимизация такого кода...
    #35470502
CTAC-KO
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Привет!

Тут такая задача - есть бд тарификации тел. разговоров. В этой бд есть такие поля
RowMark i - означает тип пакета
abonent c(7) - кто звонил
date d - дата звонка
time c(5) - время
minutes i - минут от полуночи
talk_sec i - время разговора
abonent2 c(20) - набранный номер

Здесь важен RowMark вот в каком смысле. Дело в том, что пакеты, используемые для тарификации официально имеют значение 42316, но они так же дублируются еще какимто технологическим пакетом со значением уже 42317, который обычно создается следом за пакетом 42316. Проблема в том, что:
1) дублирование какбы "неточное", т.е. в дубль-пакете 42317 может отличаться длительность разговора на +-3 секунды, а так же время начала разговора может быть +1 минута (зависит восновном от случаев когда разговор начат в последние секунды минуты), причем секунды начала разговора не отмечаются нигде и никак, т.е. точность начала разговора есть до минуты.
2) иногда в бд попадают только дубль-пакеты с меткой 42317, а их "родителя" 42316 при этом может не быть и наоборот.

Задача.
Отбросить дубль-пакеты с меткой 42317, если в наличии есть оригинал с меткой 42316, учитывая неполное и неидеальное сходство. При этом должны остаться записи с меткой 42316 непродублированные с меткой 42317 и наоборот.

Я сделал следующим образом. В отдельную бд (dbf_42316) выбираю только записи с меткой 42316, т.к. их обычно меньше, а затем по полной базе (dbfTemp) делаю SCAN/LOCATE/DELETE:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
     SELECT dbfTemp
	 SCAN FOR RowMark =  42317 

		SELECT dbf_42316
		LOCATE FOR NOT DELETED();
				AND Abonent = dbfTemp.Abonent;
				AND Date = dbfTemp.Date;
				AND (BETWEEN(Minutes, dbfTemp.Minutes- 1 ,dbfTemp.Minutes);
					OR Minutes= 1439  AND dbfTemp.Minutes= 0 )
				AND Abonent2 = dbfTemp.Abonent2;
				AND BETWEEN(Talk_Sec,dbfTemp.Talk_Sec- 3 ,dbfTemp.Talk_Sec+ 3 )
		IF FOUND()
		   DELETE
		   SELECT dbfTemp
		   DELETE
		ENDIF
	 ENDSCAN
такой способ очень медленным оказался, оно и понятно.

Я размышлял над индексацией, но так и не пришел к определенному решению.

Непонятно как это можно оптимизировать - может подскажете?

спасибо.

вфп9
...
Рейтинг: 0 / 0
Возможна ли оптимизация такого кода...
    #35470517
XAndy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Что связывает пару 42316 и 42317? Ключ какой-то есть или только составной типа кто и когда звонил?
...
Рейтинг: 0 / 0
Возможна ли оптимизация такого кода...
    #35470683
CTAC-KO
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ничего не связывает, кроме того что воочию видно что есть дубликат, т.е. ключа нет и единственная возможность это вот такое сравнение.
...
Рейтинг: 0 / 0
Возможна ли оптимизация такого кода...
    #35471198
ОТЭ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Может проиндексировать dbf_42316 по выражению Abonent+dtoc(Date)+Abonent2,
а затем в твоем скане вместо Locate использовать seek() по этому выражению и при удачном поиске
сделать цикл с построчным перебором всех совпадений на предмет сравнения минут и секунд?
...
Рейтинг: 0 / 0
Возможна ли оптимизация такого кода...
    #35471211
CTAC-KO
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
короче сам оптимизировал, но еще не уверен что все ок, хотя быстрее в разы.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
	SELECT dbf_42316
	INDEX on Abonent + DTOS(date) + abonent2 TAG indx
	SELECT dbfTemp
	SCAN FOR RowMark =  42317 
		lcSeekExpression = Abonent + DTOS(date) + abonent2
		SELECT kdf_a54c
		SEEK m.lcSeekExpression &&TAG indx
		DO WHILE m.lcSeekExpression == Abonent + DTOS(date) + abonent2
			IF NOT DELETED();
			AND (BETWEEN(Minutes, kdf2dbfTemp.Minutes- 1 ,kdf2dbfTemp.Minutes+ 1 );
				OR Minutes= 0  AND kdf2dbfTemp.Minutes= 1439 );
			AND BETWEEN(Talk_Sec,kdf2dbfTemp.Talk_Sec- 3 ,kdf2dbfTemp.Talk_Sec+ 3 )

				DELETE
				SELECT kdf2dbfTemp
				DELETE

				EXIT
			ENDIF
			SKIP
		ENDDO
	 ENDSCAN
...
Рейтинг: 0 / 0
Возможна ли оптимизация такого кода...
    #35471216
CTAC-KO
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ОТЭМожет проиндексировать dbf_42316 по выражению Abonent+dtoc(Date)+Abonent2,
а затем в твоем скане вместо Locate использовать seek() по этому выражению и при удачном поиске
сделать цикл с построчным перебором всех совпадений на предмет сравнения минут и секунд?спасибо, пришел к аналогичному :)
...
Рейтинг: 0 / 0
Возможна ли оптимизация такого кода...
    #35471429
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Можно еще ускорить если выполняются следующие предположения:
1. записи идут в хронологическом порядке как для 42316 так и для 42317
2. Запись 42316 всегда перед 42317
примерно так без промежуточной таблицы и индексов:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
SELE dbfTemp
SCAN FOR RowMark =  42316 
    lnRe = recno('dbfTemp')
    * Запоминаем содержимое записи
    lcAbonent = dbfTemp.cAbonent
    ltD = dtot(dbfTemp.date) + dbfTemp.minutes *  60 
    lnTalk_Sec = dbfTemp.Talk_Sec
    * Ищем в ближайших последующих записях дубль
    do while !eof('dbfTemp')
        skip in dbfTemp
        lnTimeDelta = dtot(dbfTemp.date) + dbfTemp.minutes *  60  - ltD
        do case
            case eof('dbfTemp') or lnTimeDelta >  60 
                 * Конец файла или ушли больше чем на  1  минуту вперед, дальше можно не искать
                 exit
            case dbfTemp.RowMark =  42317  and dbfTemp.cAbonent = lcAbonent;
                      and inlist(ltD2 - ltD1,  0 ,  60 );
                      and BETWEEN(dbfTemp.Talk_Sec lnTalk_Sec -  3 , lnTalk_Sec +  3 )
                 delete in dbfTemp
                 exit
        encase
    enddo
    go (lnRe) in dbfTemp
endscan

Даже если мои предположения 1,2 не верны, то надо индекс по ttoc(dtot(dbfTemp.date) + dbfTemp.minutes * 60, 1) + STR(RowMark, 5)

Для еще ускорения можно убрать EOF() (это довольно медленная операция) - запомнить RECNO() последней записи и проверять его внутри DO WHILE.
...
Рейтинг: 0 / 0
Возможна ли оптимизация такого кода...
    #35471444
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Не все поправил. Вместо
Код: plaintext
and inlist(ltD2 - ltD1,  0 ,  60 );
Надо
Код: plaintext
and inlist(lnTimeDelta,  0 ,  60 );
...
Рейтинг: 0 / 0
Возможна ли оптимизация такого кода...
    #35472477
Galyamov Rinat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Маленько дам вопросов для размышления.

В связи с тем, что:
> 1) дублирование какбы "неточное", т.е. в дубль-пакете 42317 может
> отличаться длительность разговора на +-3 секунды, а так же время начала
> разговора может быть +1 минута (зависит восновном от случаев когда
> разговор начат в последние секунды минуты), причем секунды начала
> разговора не отмечаются нигде и никак, т.е. точность начала разговора есть
> до минуты.

Во первых, где гарантия, что отличие именно ДО минуты, а никак не больше (ну
скажем пару минут).

Во вторых, если звонок идет на границе суток, то и даты могут быть разные.

Третье. Я в течении одной минуты совершил два (три) звонка на один и тот же
номер. Длительность разговора 5 - 10 секунд. Но звонки были, разговоры тоже.

В связи с тем, что:
> 2) иногда в бд попадают только дубль-пакеты с меткой 42317, а их
> "родителя" 42316 при этом может не быть и наоборот.

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


> Задача.

А вот задача как раз в том, чтобы сделать нормальный билинг, а не пытаться
выудить хоть что-то из имеющегося.


Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
9 сообщений из 9, страница 1 из 1
Форумы / FoxPro, Visual FoxPro [игнор отключен] [закрыт для гостей] / Возможна ли оптимизация такого кода...
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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