19.12.2017, 11:14 | #1 |
Участник
|
Помогите с кодом (ax 2009)
Как правильно написать код?
Надо добавлять данные в таблицу по определённому условию: - пока "Разница дат" в строке >= "Периоду", то добавляем новую строку со значением "Дата С" = "Дата С + Период" - иначе переходим на следующую строку Пока вышло что-то страшное X++: //rowQuota - временная таблица while select forupdate rowQuota { monthDiff = intvNo(rowQuota.DateTo, rowQuota.DateFrom, IntvScale::Month); dayDiff = intvNo(rowQuota.DateTo, rowQuota.DateFrom, IntvScale::Day); if(rowQuota.UsagePeriod <= monthDiff && dayDiff > 0) { buf2buf(rowQuota, rowQuotaTmp); do { rowQuotaTmp.DateFrom = dateMthFwd(rowQuotaTmp.DateFrom, rowQuotaTmp.UsagePeriod); rowQuotaTmp.DatePotreb = rowQuotaTmp.DateFrom; rowQuotaTmp.insert(); monthDiff = intvNo(rowQuotaTmp.DateTo, rowQuotaTmp.DateFrom, IntvScale::Month); dayDiff = intvNo(rowQuotaTmp.DateTo, rowQuotaTmp.DateFrom, IntvScale::Day); } while(rowQuotaTmp.UsagePeriod <= monthDiff && dayDiff > 0); } } |
|
19.12.2017, 11:38 | #2 |
Участник
|
Переписал так, без промежуточного буфера, всё равно долго
X++: ttsbegin; while select forupdate rowQuota { monthDiff = intvNo(rowQuota.DateTo, rowQuota.DateFrom, IntvScale::Month); dayDiff = intvNo(rowQuota.DateTo, rowQuota.DateFrom, IntvScale::Day); if(rowQuota.UsagePeriod <= monthDiff && dayDiff > 0) { do { rowQuota.DateFrom = dateMthFwd(rowQuota.DateFrom, rowQuota.UsagePeriod); rowQuota.DatePotreb = rowQuota.DateFrom; rowQuota.insert(); monthDiff = intvNo(rowQuota.DateTo, rowQuota.DateFrom, IntvScale::Month); dayDiff = intvNo(rowQuota.DateTo, rowQuota.DateFrom, IntvScale::Day); } while(rowQuota.UsagePeriod <= monthDiff && dayDiff > 0); } } ttscommit; |
|
19.12.2017, 14:56 | #3 |
Участник
|
Во-первых, if и do-while содержат одинаковые условия, превратите это в один цикл while.
Во-вторых, зачем пишете forupdate, когда не применяете ни udpate(), ни delete()? В-третьих, разделите rowQuota на две разные переменные для выборки и вставки, тогда понятнее будет код. В-четвертых, можно заменить monthDiff и dayDiff вызовом функций и сделать один вызов вместо двух.
__________________
// no comments |
|
20.12.2017, 08:29 | #4 |
Участник
|
|
|
20.12.2017, 09:16 | #5 |
Участник
|
Нельзя оптимизировать, не зная статистики. Вот этот rowQuota - это большая таблица или маленькая? Что делает intvNo? Нельзя ли сделать, чтобы выбор записей был по индексу, если таблица большая. Нельзя ли использовать insert_recordset
|
|
|
За это сообщение автора поблагодарили: MikeR (2). |
20.12.2017, 10:50 | #6 |
Участник
|
Есть временная таблица rowQuota с ДатаС, ДатаПо и Периодом. Если Период меньше, чем кол-во месяцев между датами, то создаём новую строку, где ДатаС = ДатаС+месяц(Период)
Таблица не очень большая, около 100к записей. Да, с индексом в 2 раза быстрее получилось. И решил использовать RecordInsertList X++: ttsbegin; list = new RecordInsertList(rowQuotaTmp.TableId); while select rowQuota index hint Idx { buf2buf(rowQuota, rowQuotaTmp); monthDiff = intvNo(rowQuotaTmp.DateTo, rowQuotaTmp.DateFrom, IntvScale::Month); dayDiff = intvNo(rowQuotaTmp.DateTo, rowQuotaTmp.DateFrom, IntvScale::Day); while(rowQuotaTmp.UsagePeriod <= monthDiff && dayDiff > 0) { rowQuotaTmp.DateFrom = dateMthFwd(rowQuotaTmp.DateFrom, rowQuotaTmp.UsagePeriod); rowQuotaTmp.DatePotreb = rowQuotaTmp.DateFrom; //rowQuota.insert(); list.add(rowQuotaTmp); monthDiff = intvNo(rowQuotaTmp.DateTo, rowQuotaTmp.DateFrom, IntvScale::Month); dayDiff = intvNo(rowQuotaTmp.DateTo, rowQuotaTmp.DateFrom, IntvScale::Day); } } list.insertDatabase(); ttscommit; |
|
20.12.2017, 10:53 | #7 |
Участник
|
Автору поста. Вот джоб, который уходит в бесконечный цикл при использовании одной переменной для выборки и вставки
X++: static void JobCycle(Args _args) { TmpConfigId TmpConfigId; int i; ; TmpConfigId.ItemNum = 0; TmpConfigId.insert(); while select TmpConfigId { i++; TmpConfigId.ItemNum = i; TmpConfigId.insert(); } }
__________________
-Ты в гномиков веришь? -Нет. -А они в тебя верят, смотри, не подведи их. |
|
20.12.2017, 12:04 | #8 |
Участник
|
Цитата:
Т.е. при добавлении если ДатаС + Период < ДатаПо, тогда добавляем еще 1 запись, где ДатаС = ДатаС + Период и т.д. |
|
20.12.2017, 12:40 | #9 |
Участник
|
Либо сохранить признак для условия отбора и проиндекировать его. Чтобы while select мог быстро отобрать только те записи, которые надо обрабатывать.
И прочитайте Best Practice (наименование индексов, например) |
|
20.12.2017, 18:06 | #10 |
Участник
|
Рекомендую почитать старый топик Временные таблицы и скорость работы
|
|
21.12.2017, 18:17 | #11 |
Участник
|
Если используется цикл с фиксированным шагом приращения, то имеет смысл подумать об использовании цикла for()
X++: static void Test(Args _args) { FromDate fromDate = 01\01\2017; ToDate toDate = 31\07\2017; int period = 3; TransDate transDate; ; // Исходная запись info(strFmt('с %1 по %2', fromDate, toDate)); for (transDate = global::dateMthFwd(fromDate, period); transDate < toDate; transDate = global::dateMthFwd(transDate, period)) { // новые записи info(strFmt('с %1 по %2', transDate, toDate)); } info('end'); }
__________________
- Может, я как-то неправильно живу?! - Отчего же? Правильно. Только зря... |
|
|
За это сообщение автора поблагодарили: SuperStar88 (1). |
21.12.2017, 19:03 | #12 |
Участник
|
Если таблица rowQuota временная, то использовать RecordInsertList совершенно бессмысленно. Он помогает тогда, когда таблица расположена в базе данных и сокращает количество пакетов на вставку именно в базу данных (при некоторых других условиях).
|
|
|
За это сообщение автора поблагодарили: SuperStar88 (1). |
|
|