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

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 12.09.2011, 11:45   #1  
Владимир Максимов is offline
Владимир Максимов
Участник
КОРУС Консалтинг
 
1,701 / 1195 (43) ++++++++
Регистрация: 13.01.2004
Записей в блоге: 3
Цитата:
Сообщение от S.Kuskov Посмотреть сообщение
В общем случае подцепить к имеющемуся query ещё один CustTable с типом связи exists join и наложить уже на него условие "КлиентАБВ". Затем сделав один раз queryRun.next() посмотреть вернулось ли что-нибудь.
К сожалению, это ничего не гарантирует. Если исходный запрос относительно сложен и имеет несколько таблиц-источников с "не линейной" схемой объединения, то подключение еще одного источника по Exists Join может привести к тому, что запросу "снесет крышу". Результат может оказаться парадоксальным.

В принципе, общая идея, заключающаяся в том, что нужно наложить еще один Range по этому полю - правильная. Проблема только в том, что этот Range должен подкючаться по "И", а если уже есть Range по этому же полю, скажем, настроенный пользователем, то подключение произойдет по "ИЛИ"

Именно для данного конкретного случая можно сделать "хитрый трюк". Дело в том, что определение того факта, что Range добавляется по уже существующему полю выполняется по Id поля. При этом, как правило, используется FieldId. Однако Axapta может идентифицировать поле как по FieldId, так и по ExtendedFieldId. Т.е. идентифицировать поле, как первый элемент массива.

Естесственно, что FieldId и ExtendedFieldId - это разные значения. Как следствие, построитель запросов интепретирует их как разные Range и выполняет объединение по "И".

Получается, примерно следующее

X++:
static void Job_Test(QueryRun   queryRun)
{
    Query                   queryFind;
    QueryRun                queryRunFind;
    QueryBuildDataSource    qbds;
    QueryBuildRange         qbr;
    ;
    
    queryFind = new Query(queryRun.query().pack());
    qbds = queryFind.dataSourceTable(tablenum(CustTable));
    
    // Вот этот трюк
    qbr = qbds.findRange(fieldnum(CustTable, accountNum));
    if (qbr)
    {
        // Если Range уже есть, то создаю новый Range по ExdendendFieldId
        qbr = qbds.addRange(fieldId2ext(fieldnum(CustTable, accountNum),1));
    }
    qbr.value('КлиентАБВ');
    
    
    queryRunFind = new QueryRun(queryFind);
    if (queryRunFind.next())
    {
        info("Есть такая запись");
    }
    
}

Естесственно, этот трюк работает только для полей, которые массивами не являются. Для полей-массивов можно сделать подобное только для первого элемента массива.
За это сообщение автора поблагодарили: coolibin (1), S.Kuskov (1), propeller (1).
Старый 12.09.2011, 12:41   #2  
S.Kuskov is offline
S.Kuskov
Участник
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
 
3,440 / 1775 (66) ++++++++
Регистрация: 28.04.2007
Адрес: Калуга
Цитата:
Сообщение от Владимир Максимов Посмотреть сообщение
Именно для данного конкретного случая можно сделать "хитрый трюк".
Да про данный "трюк" я в курсе. Но сдаётся мне что это поведение запросто могут "исправить" в какой-нибудь следующей версии системы.

Если выбирать из предложенных вариантов, то мне больше нравится мой про использование http://www.axaptapedia.com/Expressions_in_query_ranges

P.S.: propeller, вот уж действительно "простейшая задача"

Последний раз редактировалось S.Kuskov; 12.09.2011 в 13:32.
Старый 13.09.2011, 11:21   #3  
dn is offline
dn
Участник
Самостоятельные клиенты AX
 
486 / 159 (6) ++++++
Регистрация: 26.03.2003
Адрес: Москва
Цитата:
Сообщение от S.Kuskov Посмотреть сообщение
В общем случае подцепить к имеющемуся query ещё один CustTable с типом связи exists join и наложить уже на него условие "КлиентАБВ". Затем, сделав один раз queryRun.next(), посмотреть вернулось ли что-нибудь.
Цитата:
Сообщение от Владимир Максимов Посмотреть сообщение
К сожалению, это ничего не гарантирует. Если исходный запрос относительно сложен и имеет несколько таблиц-источников с "не линейной" схемой объединения, то подключение еще одного источника по Exists Join может привести к тому, что запросу "снесет крышу". Результат может оказаться парадоксальным.
А если использовать не ExistsJoin, а InnerJoin?
X++:
boolean findSuperCust(Query _srcQuery, CustAccount _custAccount = "КлиентАБВ")
{
    Query                   q;
    QueryRun                qr;
    QueryBuildDataSource    qbds,qbds2;
    ;
    q               = new Query(_srcQuery);
    qbds            = q.dataSourceTable(tablenum(custTable));
    qbds2           = qbds.addDataSource(tablenum(custTable));
    qbds2.fields().addField(fieldNum(custTable, AccountNum));
    qbds2.fetchMode(JoinMode::INNERJOIN);
    qbds2.relations(true);
    qbds2.addRange(fieldNum(custTable, AccountNum)).value(_custAccount);    
    qr = new QueryRun(q);
    return qr.next();  
}
За это сообщение автора поблагодарили: S.Kuskov (1).
Старый 13.09.2011, 11:38   #4  
AndyD is offline
AndyD
Участник
КОРУС Консалтинг
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
 
2,560 / 2479 (88) +++++++++
Регистрация: 20.08.2005
Цитата:
Сообщение от dn Посмотреть сообщение
X++:
    qbds2.fetchMode(JoinMode::INNERJOIN);
Вы, наверное, с JoinMode() перепутали?
Но FetchMode() тоже надо будет настраивать, если есть другие датасорсы, подключенные к CustTable.

А основная проблема с этим запросом - не может Аксапта обрабатывать большое количество вложенных подзапросов. Особенно, если они находятся на одном уровне вложенности
__________________
Axapta v.3.0 sp5 kr2
За это сообщение автора поблагодарили: dn (1), Aquarius (1).
Старый 13.09.2011, 11:55   #5  
dn is offline
dn
Участник
Самостоятельные клиенты AX
 
486 / 159 (6) ++++++
Регистрация: 26.03.2003
Адрес: Москва
Цитата:
Сообщение от AndyD Посмотреть сообщение
Вы, наверное, с JoinMode() перепутали?
Но FetchMode() тоже надо будет настраивать, если есть другие датасорсы, подключенные к CustTable.
Спасибо, за поправку.
qbds2.joinMode(JoinMode::innerJoin);
qbds2.fetchMode(QueryFetchMode::One2One);
Цитата:
Сообщение от AndyD Посмотреть сообщение
А основная проблема с этим запросом - не может Аксапта обрабатывать большое количество вложенных подзапросов. Особенно, если они находятся на одном уровне вложенности
Возможно. Но на практике, когда не проходил ExistJoin, вариант с InnerJoin проходил. Хотя согласен, что в общем случае это видимо не всегда будет работать.
Старый 13.09.2011, 12:37   #6  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
Цитата:
Сообщение от AndyD Посмотреть сообщение
А основная проблема с этим запросом - не может Аксапта обрабатывать большое количество вложенных подзапросов. Особенно, если они находятся на одном уровне вложенности
может-может.
только в случае нескольких вложенных таблиц Аксапта возвращает записи ПОСЛЕДОВАТЕЛЬНО.

я уже ссылку давал
Цитата:
Сообщение от mazzy Посмотреть сообщение
вариант S.Kuskov: приджойнить exist join тоже не подойдет. поскольку в запросе уже может быть join. http://msdn.microsoft.com/en-us/libr...36(AX.10).aspx
прикладываю и картинку
Изображения
 
__________________
полезное на axForum, github, vk, coub.
Старый 13.09.2011, 13:07   #7  
dn is offline
dn
Участник
Самостоятельные клиенты AX
 
486 / 159 (6) ++++++
Регистрация: 26.03.2003
Адрес: Москва
Цитата:
Сообщение от mazzy Посмотреть сообщение
прикладываю и картинку
Эта картинка относится к варианту связи источников данных OuterJoin (судя по информации по приведенной ссылке). А как это соотносится с Exists и Inner Join'ами?
Старый 13.09.2011, 13:36   #8  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
Цитата:
Сообщение от dn Посмотреть сообщение
А как это соотносится с Exists и Inner Join'ами?
хорошо соотносится.
проверьте.
Миниатюры
Нажмите на изображение для увеличения
Название: 1.PNG
Просмотров: 270
Размер:	121.5 Кб
ID:	7147  
Вложения
Тип файла: xpo Report_Report1.xpo (6.7 Кб, 239 просмотров)
__________________
полезное на axForum, github, vk, coub.
Старый 13.09.2011, 14:14   #9  
S.Kuskov is offline
S.Kuskov
Участник
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
 
3,440 / 1775 (66) ++++++++
Регистрация: 28.04.2007
Адрес: Калуга
Цитата:
Сообщение от AndyD Посмотреть сообщение
Но FetchMode() тоже надо будет настраивать, если есть другие датасорсы, подключенные к CustTable.
Про FetchMode хорошо написал Иван Кашперук Связывание источников данных в запросах
Цитата:
Сообщение от AndyD Посмотреть сообщение
А основная проблема с этим запросом - не может Аксапта обрабатывать большое количество вложенных подзапросов. Особенно, если они находятся на одном уровне вложенности
Соглашусь с тем что замена "exists join" на "inner join" во многих случаях поможет, но не всегда.
Проблема с "exists join" связана с тем, что если такой exists будет вставлен между двумя таблицами уже соеденёнными при помощи "inner join", то результирующий запрос получится не всегда ожиданным.

Например, такой гипотетический код:
Код:
select Table1
exists join Table3 where Table3.id == Table1.id
inner join Table2 where Table2.id == Table1.id
будет преобразован примерно вот в такой запрос:
Код:
table1 where exists (select Table3 join table2)
Если обойтись без Exists join и всегда использовать Inner join, то тогда проблема может появится уже по другой причине. Может быть превышено максимальное число приджойненных таблиц.
За это сообщение автора поблагодарили: dn (1).
Старый 13.09.2011, 16:27   #10  
dn is offline
dn
Участник
Самостоятельные клиенты AX
 
486 / 159 (6) ++++++
Регистрация: 26.03.2003
Адрес: Москва
Цитата:
Сообщение от mazzy Посмотреть сообщение
хорошо соотносится.
проверьте.
Такое поведение как раз задается fetchmode 1:n

Последний раз редактировалось dn; 13.09.2011 в 16:32.
Старый 13.09.2011, 11:45   #11  
S.Kuskov is offline
S.Kuskov
Участник
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
 
3,440 / 1775 (66) ++++++++
Регистрация: 28.04.2007
Адрес: Калуга
Цитата:
Сообщение от mazzy Посмотреть сообщение
или не содержал И искомого значения в базе вообще нет.
Ну это легко проверить простым дополнительным запросом.


Цитата:
Сообщение от AndyD Посмотреть сообщение
Кстати, никто не обращал внимание, что критерии со статусом Hidden - не такие уж и невидимые?
Достаточно в форме расширенного фильтра вызвать расширенный фильтр (в 2009-й через комбинацию клавишь) и нажать Ok
Ух ты. Такое поведение нужно исправлять. Например так. На форме SysQueryForm, в методе init() датасурса Range
X++:
void init()
{

    super();

    selectRangeRecords = this.query().dataSourceNo(1).addRange(fieldnum(TmpSysQuery, RangeStatus));
    selectRangeRecords.value('!' + enum2str(RangeStatus::Hidden));

    selectRangeRecords.status(RangeStatus::Locked); // <<--
}

Цитата:
Сообщение от dn Посмотреть сообщение
А если использовать не ExistsJoin, а InnerJoin?
О! Здравая идея. А для оптимизации тогда ещё можно задать addSelectionField со значением SelectionField:atabase по какому-нибудь полю индекса
Теги
query, как правильно

 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
Очередной вопрос про Query rkrivov DAX: Программирование 45 16.10.2013 19:16
Вопрос по query? Hidden DAX: Программирование 1 31.07.2007 18:10
Вопрос по query и join tischenko DAX: Программирование 2 20.07.2005 13:05
Вопрос по запросу (query) Александр_1975 DAX: Программирование 2 23.01.2004 17:35
Вопрос знатокам QBE и Query в AXAPTA Maxim Gorbunov DAX: Программирование 6 27.12.2002 13:19

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

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

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