04.01.2012, 11:43 | #1 |
Участник
|
Запрос к InventSum с InventLocationId
*** Вынесено из InventLocationId в InventTrans, sukhanchik ***
Здраствуйте , Мы сделали InventLocationId в InventSum'е . Помогло и облегчило дело с рапоратми по складам . Хотел попросить совета . Бухалтерия требует отчетов складов , в которых были остатки в начяле периода и остатки в конце . Я сделаю такое в одной из своей классе : X++: Query qInvSum1( Query qry ) { QueryBuildDataSource qBSSum, qBSTrn; ; qBSSum = qry.dataSourceTable( TableNum( InventSum ) ); qBSSum.addSortIndex( indexnum( InventSum, LocateItemIdx ) ); qBSSum.indexIsHint( true ); qBSTrn = qBSSum.addDataSource( tableNum( InventTrans ) ); qBSTrn.addLink( fieldNum( InventTrans, InventDimId ), fieldNum( InventSum, InventDimId ) ); qBSTrn.addLink( fieldNum( InventTrans, ItemId ), fieldNum( InventSum, ItemId ) ); qBSTrn.addSortIndex( indexNum( InventTrans, DimIdIdx ) ); qBSTrn.indexIsHint( true ); qBSTrn.joinMode( JoinMode::ExistsJoin ); qBSTrn.firstOnly( true ); qBSTrn.fetchMode( QueryFetchMode::One2One ); qBSTrn.addRange( fieldNum( InventTrans, DatePhysical ) ).value( queryRange( dBgn, dateMax() ) ); return qry; } Дело в том что некоторые товары из InventSum может быть неподвигались и в InventTrans'e нету записей с ними . Тогда я вынужден сделать второй запрос : X++: Query qInvSum2( Query qry ) { QueryBuildDataSource qBSSum, qBSTrn; ; qBSSum = qry.dataSourceTable( TableNum( InventSum ) ); qBSSum.addSortIndex( indexnum( InventSum, LocateItemIdx ) ); qBSSum.indexIsHint( true ); qBSSum.addRange( fieldNum( InventSum, PhysicalInvent ) ).value( queryvalue( '!= 0' ) ); qBSTrn = qBSSum.addDataSource( tableNum( InventTrans ) ); qBSTrn.addLink( fieldNum( InventTrans, InventDimId ), fieldNum( InventSum, InventDimId ) ); qBSTrn.addLink( fieldNum( InventTrans, ItemId ), fieldNum( InventSum, ItemId ) ); qBSTrn.addSortIndex( indexNum( InventTrans, DimIdIdx ) ); qBSTrn.indexIsHint( true ); qBSTrn.joinMode( JoinMode::NoExistsJoin ); qBSTrn.firstOnly( true ); qBSTrn.fetchMode( QueryFetchMode::One2One ); qBSTrn.addRange( fieldNum( InventTrans, DatePhysical ) ).value( queryRange( dBgn, dateMax() ) ); qBSTrn.addRange( fieldNum( InventTrans, DatePhysical ) ).value( queryvalue( strfmt( ">=%1", dBgn ) ) ); return qry; } Заранее спасибо ! Последний раз редактировалось sukhanchik; 06.01.2012 в 00:20. |
|
04.01.2012, 12:06 | #2 |
MCITP
|
2 Rimantas
Одним запросом это можно сделать через Outer Join с группировкой, примерно так: X++: Select sum(xxxQty), sum(yyyAmount), ... from InventSum group by ItemId, InventDimId, ... outer join InventTrans group by ItemId where InventTrans.InventDimId == InventSum.InventDimId && InventTrans.ItemId == InventSum.ItemId && InventTrans.DatePhysical >= dBgn; В цикле проверять заполненность поля InventTrans.ItemId - если есть, то это ваш первый случай, если нет - второй. Насколько это будет быстрее или медленнее, и, соответсвенно, целесообразно использовать, проверьте сами на своих данных.
__________________
Zhirenkov Vitaly |
|
04.01.2012, 12:14 | #3 |
Участник
|
Мне кажется не стоит гнаться за одним запросом.
Лучше сделать несколько оптимизированных запросов, а промежуточные данные хранить во времянке или в мапе, если их немного. |
|
04.01.2012, 14:18 | #4 |
Участник
|
Цитата:
Сообщение от ZVV
2 Rimantas
Одним запросом это можно сделать через Outer Join с группировкой, примерно так: X++: Select sum(xxxQty), sum(yyyAmount), ... from InventSum group by ItemId, InventDimId, ... outer join InventTrans group by ItemId where InventTrans.InventDimId == InventSum.InventDimId && InventTrans.ItemId == InventSum.ItemId && InventTrans.DatePhysical >= dBgn; В цикле проверять заполненность поля InventTrans.ItemId - если есть, то это ваш первый случай, если нет - второй. Насколько это будет быстрее или медленнее, и, соответсвенно, целесообразно использовать, проверьте сами на своих данных. товар кол1 приход отход кол2 тов1 0 10 -10 0 - в инветСумме уже нету , но были движения , тов2 10 0 -10 0 - тоже самое , тов22 0 10 0 10 - были движения , есть в инвентсумме , тов3 10 0 0 10 - нету движении ... В моем варянте , 2-ом , чтобы неискать я сделал условие "!= 0" для количества в инвентсумме - чтобы поскорее все работало ... А можно как нибудь ещё добавить "или" в query ИнвентСума такое ? |
|
06.01.2012, 00:00 | #5 |
MCITP
|
Цитата:
Сообщение от Rimantas
Дело в том что в отчете может так выглядит :
товар кол1 приход отход кол2 тов1 0 10 -10 0 - в инветСумме уже нету , но были движения , тов2 10 0 -10 0 - тоже самое , тов22 0 10 0 10 - были движения , есть в инвентсумме , тов3 10 0 0 10 - нету движении ... В моем варянте , 2-ом , чтобы неискать я сделал условие "!= 0" для количества в инвентсумме - чтобы поскорее все работало ... А можно как нибудь ещё добавить "или" в query ИнвентСума такое ? 2. Цитата:
А можно как нибудь ещё добавить "или" в query ИнвентСума такое ?
Тогда ответ - Нет. Придётся анализировать внутри цикла, что либо есть InventTrans.ItemId || есть InventSum.PhysicalInvent...
__________________
Zhirenkov Vitaly |
|
06.01.2012, 14:27 | #6 |
Участник
|
Хочу предостеречь тех, кто решит добавить поле InventLicationId в таблицу InventSum.
В ранней версии (3,0) делали такое. Это давало (наверное) какие то улучшения по производительности некоторых "самописных" отчетов, едва заметные. Но с переходом на ax2009 всплыла такая особенность. Дело в том, что для определения (например) остатков номенклатуры внутри транзакции в новых версиях Ax используются данные из двух таблиц - InventSum - InventSumDelta Поэтому делая запрос лишь к InventSum (из собственно написанного кода) внутри транзакции можно получить искаженные данные. Это конечно, не относится к работе отчетов, которые будут работать нормально. Но попытка получить остатки по номенклатуре (например при резервировании) делая прямой запрос к inventSum вернет ошибочный результат, если этот запрос делается в транзакции, в которой по данной номенклатуре были изменения в количестве... Вывод: Использовать стандартные классы inventOnHand, тогда проблем не будет. В общем от поля InventLicationId пришлось отказаться. При этом потери скорости работы старых отчетов не заметно... |
|
|
За это сообщение автора поблагодарили: Logger (6), Bega (5). |
06.01.2012, 14:46 | #7 |
Участник
|
Добавлю - ваше замечание по поводу InventSum и inventOnHand не связано с добавлением поля InventLocationId в InventSum. Это просто особенность работы 2009-й Аксапты, которую надо учитывать при разработке. Пока транзакция незакоммичена - Inventsum находится в состоянии на момент начало транзакции, поэтому для получения корректных остатков в середине транзакции неправильно писать запросы непосредственно к InventSum. (в 3-ке было можно). Надо, как вы справедливо указали, использовать класс inventOnHand, который добавит незакоммиченные изменения из InventSumDelta и вернет корректный остаток независимо от того - начата транзакция или нет.
|
|
06.01.2012, 17:05 | #8 |
Участник
|
Цитата:
Сообщение от Logger
Добавлю - ваше замечание по поводу InventSum и inventOnHand не связано с добавлением поля InventLocationId в InventSum. Это просто особенность работы 2009-й Аксапты, которую надо учитывать при разработке. Пока транзакция незакоммичена - Inventsum находится в состоянии на момент начало транзакции, поэтому для получения корректных остатков в середине транзакции неправильно писать запросы непосредственно к InventSum. (в 3-ке было можно). Надо, как вы справедливо указали, использовать класс inventOnHand, который добавит незакоммиченные изменения из InventSumDelta и вернет корректный остаток независимо от того - начата транзакция или нет.
|
|
07.01.2012, 18:06 | #9 |
Участник
|
Это может быть связано с тем, если у вас построение отчета происходит по алгоритму не сначала времен. А с использованием inventSum. Принцип такой : Получаем остатки на сегодня (InventSum). Вычисляем приход + расход от указанной вами даты до сегодня. Можем вычислить остатки на указанную вами дату. Затем вычисляем приход. Затем расход. А остатки на конец месяца путем сложения остатки на начало + приход - расход.Такой принцип работает быстрее стандартной оборотки в ваших версиях, за счет того, что при выборке данных используется маленький период(а не сначала времен). Но в этом есть подвох (он не частый но иногда происходит).Пока вы получаете остатки в наличии на сегодня, кто-то может разнести журнал, закупку и т.д.Т.е. вы в процессе выполнения получили остаток без учета этого разнесенного журнала. Затем ваш алгоритм переходит к получению приъхода, расхода и т.д. И вот тут вы получите, что в приход(или расход) попало количество этого УЖЕ разнесенного журнала.В итоге данные не корректные. Если вы запустите этот отчет еще раз, все будет нормально. У нас, такое происходит периодически.
__________________
-Ты в гномиков веришь? -Нет. -А они в тебя верят, смотри, не подведи их. |
|
09.01.2012, 10:30 | #10 |
Участник
|
Цитата:
Сообщение от Pustik
Это может быть связано с тем, если у вас построение отчета происходит по алгоритму не сначала времен. А с использованием inventSum. Принцип такой : Получаем остатки на сегодня (InventSum). Вычисляем приход + расход от указанной вами даты до сегодня. Можем вычислить остатки на указанную вами дату. Затем вычисляем приход. Затем расход. А остатки на конец месяца путем сложения остатки на начало + приход - расход.Такой принцип работает быстрее стандартной оборотки в ваших версиях, за счет того, что при выборке данных используется маленький период(а не сначала времен). Но в этом есть подвох (он не частый но иногда происходит).Пока вы получаете остатки в наличии на сегодня, кто-то может разнести журнал, закупку и т.д.Т.е. вы в процессе выполнения получили остаток без учета этого разнесенного журнала. Затем ваш алгоритм переходит к получению приъхода, расхода и т.д. И вот тут вы получите, что в приход(или расход) попало количество этого УЖЕ разнесенного журнала.В итоге данные не корректные. Если вы запустите этот отчет еще раз, все будет нормально. У нас, такое происходит периодически.
while ( qr.next() ) { inventDim = qr.get( tableNum( InventDim ) ); InventSum = qr.get( tableNum( InventSum ) ); ... и т.д. } Наверно для того , чтобы избежaть такое , надо ещё раз взять переменную inventSum2 . Например - inventSum2 = InventSum::findRecord( inventSum.RecId ) . Вот тогда данные в InventSum-е будет правильные и точка отчета в данный момент тоже правильное ... Все - попробываю ... |
|
09.01.2012, 19:00 | #11 |
Участник
|
Цитата:
Сообщение от Rimantas
есть несовпадение InventSum-а и InventTrans-a . То есть в том смысле , когда програма сделает query в реальном времени , оно хватает данные от InventSum как такие . И вот когда другие делает попрваки , то в тот момент InventTrans пополняеться записями , а InventSum от query - остаеться непоправленным . Вот ето место необновляеться ( например ) :
while ( qr.next() ) { inventDim = qr.get( tableNum( InventDim ) ); InventSum = qr.get( tableNum( InventSum ) ); ... и т.д. } |
|
11.01.2012, 22:30 | #12 |
Участник
|
Цитата:
У нас, почти во все важные оборотки встроена такая возможность.
__________________
-Ты в гномиков веришь? -Нет. -А они в тебя верят, смотри, не подведи их. |
|