AXForum  
Вернуться   AXForum > Microsoft Dynamics AX > DAX: Программирование
All
Забыли пароль?
Зарегистрироваться Правила Справка Пользователи Сообщения за день Поиск Все разделы прочитаны

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 09.06.2007, 05:00   #1  
Михаил Петрович is offline
Михаил Петрович
Участник
 
20 / 10 (1) +
Регистрация: 21.03.2007
? Фактуры. Помогите с запросом.
Здравия всем...

Вот такой вот запросик при обработке фактур занимает сейчас секунд 30 минимум при выполнении...
Местонахождение - classes\FactureCalcSettlement_RU\calcFactureAmounts line 50

X++:
// Process line markups
    while select sum(LineAmount), sum(VAT), sum(TaxAmount),sum(Qty), maxOf(ItemName) from factureTrans
        group by TaxCode, Dimension, ExchRate,InventTransId, InternalInvoiceId,InvoiceId,NumberSequenceGroup,markupRefRecId
        exists join custVendInvoiceTrans
        exists join markupTrans
        where factureTrans.FactureId            == _factureJour.FactureId           &&
              factureTrans.Module               == module                           &&
              factureTrans.FactureLineType      == FactureLineType_RU::Markup       &&
              markupTrans.RecId                 == factureTrans.MarkupRefRecId      &&
              markupTrans.TransTableId          == custVendInvoiceTrans.TableId     &&
              custVendInvoiceTrans.RecId        == markupTrans.TransRecId           &&
              custVendInvoiceTrans.SalesPurchId == _custVendInvoiceJour.Num         &&
              custVendInvoiceTrans.InvoiceNum   == _custVendInvoiceJour.InvoiceId   &&
              custVendInvoiceTrans.InvoiceDate  == _custVendInvoiceJour.InvoiceDate &&
              (module == FactureModule_RU::Cust ||
               (module == FactureModule_RU::Vend &&
                custVendInvoiceTrans.PurchInternalInvoiceId == _custVendInvoiceJour.PurchInternalInvoiceId)) &&
              custVendInvoiceTrans.NumberSequenceGroupId
                                                == _custVendInvoiceJour.NumberSequenceGroupId
    {
        this.addFactureTransAmounts(factureAmounts, factureTrans, _factureJour);
    }
При преобразовании его в нечто вот такое, выполнение запроса сводится к сотням миллисекунд, но есть некоторая неуверенность однозначности запросов

X++:
// Process line markups
    while select sum(LineAmount), sum(VAT), sum(TaxAmount),sum(Qty), maxOf(ItemName) from factureTrans

        group by TaxCode, Dimension, ExchRate,InventTransId, InternalInvoiceId,InvoiceId,NumberSequenceGroup,markupRefRecId

        where factureTrans.FactureId            == _factureJour.FactureId           &&
              factureTrans.Module               == module                           &&
              factureTrans.FactureLineType      == FactureLineType_RU::Markup      
        
        exists join markupTrans
        where markupTrans.RecId                 == factureTrans.MarkupRefRecId      &&
              markupTrans.TransTableId          == custVendInvoiceTrans.TableId   

        exists join custVendInvoiceTrans
        where custVendInvoiceTrans.RecId        == markupTrans.TransRecId           &&
              custVendInvoiceTrans.SalesPurchId == _custVendInvoiceJour.Num         &&
              custVendInvoiceTrans.InvoiceNum   == _custVendInvoiceJour.InvoiceId   &&
              custVendInvoiceTrans.InvoiceDate  == _custVendInvoiceJour.InvoiceDate &&
              (module == FactureModule_RU::Cust ||
               (module == FactureModule_RU::Vend &&
                custVendInvoiceTrans.PurchInternalInvoiceId == _custVendInvoiceJour.PurchInternalInvoiceId)) &&
              custVendInvoiceTrans.NumberSequenceGroupId
                                                == _custVendInvoiceJour.NumberSequenceGroupId
    {
        this.addFactureTransAmounts(factureAmounts, factureTrans, _factureJour);
    }
С нетерпением жду совета :-)
Старый 09.06.2007, 08:06   #2  
miklenew is offline
miklenew
Участник
Аватар для miklenew
MCBMSS
1C
Лучший по профессии 2009
 
1,688 / 433 (18) +++++++
Регистрация: 10.07.2006
Адрес: г. Ликино-Дулёво
Где то видел на форуме, что второй вариант правильнее. Да вы выгрузите куда нибудь результат по какому нибудь столбцу и сверьте. Будете точно уверены, что нигде не ошиблись.
Старый 09.06.2007, 08:58   #3  
Raven Melancholic is offline
Raven Melancholic
Участник
Аватар для Raven Melancholic
Самостоятельные клиенты AX
Лучший по профессии 2015
 
2,164 / 1296 (48) ++++++++
Регистрация: 21.03.2005
Адрес: Москва-Петушки
Все правильно. Это место практически все переделывают, так как при exists join очень важно, чтобы в условии подзапроса не было фильтрации основного запроса (если посмотреть запрос, который отправляется на сервер в первом случае, станет понятно почему).
Кстати ,еще одним вариантам переделки является изменение exist join на простой join RecId - в этом случае сервер сам справится с оптимизацией запроса.
Старый 09.06.2007, 13:22   #4  
Михаил Петрович is offline
Михаил Петрович
Участник
 
20 / 10 (1) +
Регистрация: 21.03.2007
Большое спасибо за ответы :-)
Старый 09.06.2007, 15:23   #5  
kashperuk is offline
kashperuk
Участник
Аватар для kashperuk
MCBMSS
Соотечественники
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,361 / 2084 (78) +++++++++
Регистрация: 30.05.2004
Адрес: Atlanta, GA, USA
а разве это в последних сервис паках не было исправлено? У вас какой, кстати?
Старый 12.06.2007, 15:15   #6  
Михаил Петрович is offline
Михаил Петрович
Участник
 
20 / 10 (1) +
Регистрация: 21.03.2007
У нас SP3 стоит...
Старый 12.06.2007, 16:57   #7  
konopello is offline
konopello
SAP
SAP
 
628 / 76 (4) ++++
Регистрация: 08.11.2005
Адрес: Минск
Цитата:
так как при exists join очень важно, чтобы в условии подзапроса не было фильтрации основного запроса
а можете пояснить что вы этим хотели сказать, просто много раз уже сталуивался что exists глючит но так и не понел чего.
Старый 12.06.2007, 17:01   #8  
kashperuk is offline
kashperuk
Участник
Аватар для kashperuk
MCBMSS
Соотечественники
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,361 / 2084 (78) +++++++++
Регистрация: 30.05.2004
Адрес: Atlanta, GA, USA
Цитата:
Сообщение от konopello Посмотреть сообщение
а можете пояснить что вы этим хотели сказать, просто много раз уже сталуивался что exists глючит но так и не понел чего.
на сервер в этом случае уйдет запрос вида

X++:
select .... from table where (select * from table2...)
вместо
X++:
select ... from table exists join table2
Старый 12.06.2007, 17:08   #9  
konopello is offline
konopello
SAP
SAP
 
628 / 76 (4) ++++
Регистрация: 08.11.2005
Адрес: Минск
Цитата:
чтобы в условии подзапроса не было фильтрации основного запроса
Т.е. если запрос имеет вид
X++:
select table1 
        where table1.field1 == "11" 
exists join table2 
        where table2.field1 == table1.field1
то на сервер поедет запрос
X++:
select .... from table where (select * from table2...)
вместо
X++:
select ... from table exists join table2
Это так?

Последний раз редактировалось konopello; 12.06.2007 в 17:11.
Старый 12.06.2007, 17:12   #10  
kashperuk is offline
kashperuk
Участник
Аватар для kashperuk
MCBMSS
Соотечественники
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,361 / 2084 (78) +++++++++
Регистрация: 30.05.2004
Адрес: Atlanta, GA, USA
Цитата:
Сообщение от konopello Посмотреть сообщение
Это так?
1. Это уже исправлено в последних сервис паках.
2. Нет, по-моему в приведенном вами примере все уйдек как надо.

Глюки будут, если в подзапросе есть фильтрация полей основного запроса, к примеру

X++:
select table1 
        where table1.field1 == "11" 
exists join table2 
        where table1.field3 == "321" &&
                  table2.field1 == table1.field1;
За это сообщение автора поблагодарили: konopello (1).
Старый 12.06.2007, 17:19   #11  
konopello is offline
konopello
SAP
SAP
 
628 / 76 (4) ++++
Регистрация: 08.11.2005
Адрес: Минск
Благодарствю за ответ, хорошо что у меня нет привычки писать такие запросы.
Старый 14.06.2007, 05:08   #12  
Михаил Петрович is offline
Михаил Петрович
Участник
 
20 / 10 (1) +
Регистрация: 21.03.2007
Продолжаем эпопею с фактурами dsExecuteMarkup() класса FactureEditLinesEngineVend_RU

В методе
X++:
public void dsExecuteMarkup()
{
    MarkupTrans      markupCursor = markupDS.cursor();
    VendInvoiceJour  tJour        = vendInvoiceJourDS.cursor();
    VendInvoiceTrans tTrans;

    super();

    select markupCursor
        where   markupCursor.CustVendPosted_RU                         &&
              ! markupCursor.ItemPosted_RU
    exists join tTrans
        where (
               markupCursor.TransTableId  == tTrans.TableId            &&
               markupCursor.TransRecId    == tTrans.RecId              &&
               tTrans.PurchID             == tJour.PurchId             &&
               tTrans.InvoiceId           == tJour.InvoiceId           &&
               tTrans.InvoiceDate         == tJour.InvoiceDate         &&
               tTrans.NumberSequenceGroup == tJour.NumberSequenceGroup &&
               tTrans.InternalInvoiceId   == tJour.InternalInvoiceId
              )
              ||
              (
               markupCursor.TransTableId  == tJour.TableId             &&
               markupCursor.TransRecId    == tJour.RecId
              );
}
Происходит "прогулка" по VendInvoiceTrans и estimated cost запроса становится буквально от 5000 до 58200 - пока большей "стоимости" sql мониторинг не выдавал.

Так вот теоретический вопрос:

Почему в подзапросе начинается проверка вида

X++:
       markupCursor.TransTableId  == tTrans.TableId            &&
               markupCursor.TransRecId    == tTrans.RecId   
           

               markupCursor.TransTableId  == tJour.TableId             &&
               markupCursor.TransRecId    == tJour.RecId
Особенно первая часть до "или"... Мы ж вроде как ищем данные в tTrans, а не наоборот...

То есть

X++:
        tTrans.TableId  == markupCursor.TransTableId            &&
                tTrans.RecId  == markupCursor.TransRecId
Или нет?..

А вот сам sql запрос

X++:
SELECT A.TRANSTABLEID,A.TRANSRECID,A.LINENUM,A.MARKUPCODE,
A.CURRENCYCODE,A.VALUE,A.TAXAMOUNT,A.POSTED,A.VOUCHER,
A.TRANSDATE,A.TXT,A.TAXGROUP,A.TAXITEMGROUP,A.MARKUPCATEGORY,
A.TAXAUTOGENERATED,A.TAXWRITECODE,A.MODULECATEGORY,A.ORIGRECID,
A.ORIGTABLEID,A.MODULETYPE,A.DEL_FULLYINVOICED,A.KEEP,
A.CALCULATEDAMOUNT,A.FACTUREDAMOUNT_RU,A.CUSTVENDPOSTED_RU,
A.ITEMPOSTED_RU,A.TAXVALUEVAT_RU,A.TAXAMOUNTVAT_RU,
A.TAXAMOUNTEXCISE_RU,A.TAXVATTYPE_RU,A.SOURCETABLEID,
A.SOURCERECID,A.MARKUPALLOCATEAFTER,A.INVENTTRANSID,A.RECID FROM MARKUPTRANS A WHERE ((A.DATAAREAID='ret') AND ((A.CUSTVENDPOSTED_RU<>0) AND ((A.ITEMPOSTED_RU=0)))) 

AND EXISTS (SELECT 'x' FROM VENDINVOICETRANS B WHERE 
((B.DATAAREAID='ret') AND (((((([COLOR="Red"]
((A.TRANSTABLEID=492) [/COLOR]A[COLOR="#ff0000"]ND
 (A.TRANSRECID=B.RECID[/COLOR])) AND (B.PURCHID='         ???00019730'))
 AND (B.INVOICEID='               15548')) AND 
(B.INVOICEDATE={ts '2005-10-02 00:00:00.000'})) AND 
(B.NUMBERSEQUENCEGROUP=' ')) AND
 (B.INTERNALINVOICEID='         ???00013750')) [COLOR="#ff0000"]OR ((A.TRANSTABLEID=491) AND (A.TRANSRECID=277411563))[/COLOR]))) 
ORDER BY A.DATAAREAID,A.TRANSRECID,A.TRANSTABLEID,A.LINENUM OPTION(FAST 1)
Если вынести эту проверку до exist join суть запроса ведь не поменяется?..

На предложение "возьми да и проверь" могу ответить лишь отказом ибо почему-то даже при известных данных без изменений этот запрос выдает пустую результирующую табличку...
Хотя подозреваю, что где-то что-то не так делаю :-)
Старый 15.06.2007, 15:18   #13  
gl00mie is offline
gl00mie
Участник
MCBMSS
Most Valuable Professional
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,684 / 5798 (201) ++++++++++
Регистрация: 28.11.2005
Адрес: Москва
Записей в блоге: 3
Цитата:
Сообщение от Михаил Петрович Посмотреть сообщение
Почему в подзапросе начинается проверка вида
X++:
               markupCursor.TransTableId  == tTrans.TableId            &&
               markupCursor.TransRecId    == tTrans.RecId   
           

               markupCursor.TransTableId  == tJour.TableId             &&
               markupCursor.TransRecId    == tJour.RecId
Особенно первая часть до "или"... Мы ж вроде как ищем данные в tTrans, а не наоборот...
Потому что в TSQL пишется
Код:
select  *
from    markupTrans      m
join    vendInvoiceTrans t
on      m.transTableId = t.tableId  and
        m.transRecId   = t.recId
т.е. в JoinCondition первым идет поле из "левой" таблицы.
Старый 18.06.2007, 02:33   #14  
Михаил Петрович is offline
Михаил Петрович
Участник
 
20 / 10 (1) +
Регистрация: 21.03.2007
Спасибо за разъяснение!

А идей по ускорению сей процедуры случайно нет?..
 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
Помогите с запросом Antonuch DAX: Программирование 4 21.06.2007 15:46
Помогите с запросом leshy DAX: Программирование 40 31.05.2007 14:51
Помогите с запросом.. DarkBear DAX: Программирование 2 15.08.2005 13:38
Помогите с SQL запросом malex DAX: Программирование 8 26.07.2005 13:43
Пожалуйста, помогите с запросом chel DAX: Программирование 19 12.07.2004 11:53
Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход

Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 10:39.