![]() |
#1 |
Участник
|
вопрос по Query
Простейшая задача: есть query по таблице CustTable с какими-то условиями.
Есть значение "КлиентАБВ". Нужно проверить, есть ли запись с таким значением поля AccountNum в имеющемся query. Понято, через queryRun.next() можно перебрать все записи и условием проверить, но хотелось бы по быстрей и покрасивей. |
|
![]() |
#2 |
Участник
|
А что если создать копию этого query и добавить туда ренж по AccountNum, много перебирать не надо, поле уникальное – достаточно одного одного queryRun.next().
__________________
Не принимайте жизнь всерьез - это временное явление... ![]() |
|
![]() |
#3 |
Участник
|
В общем случае подцепить к имеющемуся query ещё один CustTable с типом связи exists join и наложить уже на него условие "КлиентАБВ". Затем, сделав один раз queryRun.next(), посмотреть вернулось ли что-нибудь.
to Jorj: если в исходном query на поле AccountNum уже есть условие, то ещё одно условие "КлиентАБВ". добавится к нему через "ИЛИ". Ещё вариант, чтобы добится присоединения условия через "И",можно воспользоваться "расширенным синтаксисом" range (http://www.axaptapedia.com/Expressions_in_query_ranges) и добавить условие "КлиентАБВ" через какое-нибудь свободное поле (например через recid. Но и тогда в общем случае могут возникнуть проблемы совместимости, например при наличии RLS: Что делает RLS с связанными запросами в отчете). Last edited by S.Kuskov; 12.09.2011 at 12:57. |
|
![]() |
#4 |
Участник
|
Quote:
X++: boolean findSuperCust(Query _srcQuery, CustAccount _custAccount = "КлиентАБВ") { Query q = new Query(q); // создаем копию QueryRun qr; // устанавливаем новый критерий или меняем существующий findOrCreateRange_W(q.dataSourceTable(tablenum(custTable)),fieldnum(custTable, AccountNum), QueryValue(_custAccount)); // выполняем запрос qr = new QueryRun(q); return qr.next(); } |
|
![]() |
#5 |
Участник
|
Quote:
Вы о каких эфектах? В случае если пользовательский фильтр по полю accountNum имеет место быть, то тогда просто взять и заменить его на "КлиентАБВ" можно только если истинно Global::inRange(Range.value, "КлиентАБВ"). В общем случае пользовательских фильтров может быть несколько, значит проверить прийдётся их все, т.е. нужен цикл. ИМХО добавить ещё одну связку по exists join будет проще. Ещё раз. Все эти извращения нужны если "пользовательский фильтр по полю accountNum имеет место быть". Если нет, то достаточно совета Jorj и mazzy |
|
|
This post has been rated by: mazzy (2). |
![]() |
#6 |
Участник
|
Quote:
В принципе, общая идея, заключающаяся в том, что нужно наложить еще один 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("Есть такая запись"); } } Естесственно, этот трюк работает только для полей, которые массивами не являются. Для полей-массивов можно сделать подобное только для первого элемента массива. |
|
|
This post has been rated by: coolibin (1), S.Kuskov (1), propeller (1). |
![]() |
#7 |
Участник
|
Quote:
Если выбирать из предложенных вариантов, то мне больше нравится мой ![]() P.S.: propeller, вот уж действительно "простейшая задача" ![]() Last edited by S.Kuskov; 12.09.2011 at 13:32. |
|
![]() |
#8 |
Участник
|
Если ровно один, то findOrCreateRange_W изменит критерий на 'КлиентАБВ' по полю.
Если меньше одного, то findOrCreateRange_W добавит критерий 'КлиентАБВ' по полю. А вот если больше одного, то findOrCreateRange_W изменит один из критериев (первый попавшийся) на 'КлиентАБВ'. Все критерии по этому полю будут действовать через ИЛИ. Quote:
А ведь точно. |
|
![]() |
#9 |
Участник
|
мне кажется что достаточно будет добавить ",КлиентАБВ", если критерий уже существует.
X++: boolean findSuperCust(Query _srcQuery, CustAccount _custAccount = "КлиентАБВ") { Query q = new Query(_srcQuery); // создаем копию QueryBuildRange qbr; QueryRun qr; // устанавливаем новый критерий или меняем существующий qbr = SysQuery::findOrCreateRange(q.dataSourceTable(tablenum(custTable)),fieldnum(custTable, AccountNum)); qbr.value( queryRangeConcat(qbr.value(), _custAccount) ); // добавляем к уже существующему или устанавливаем вместо пустого // выполняем запрос qr = new QueryRun(q); return qr.next(); } |
|
![]() |
#10 |
Участник
|
queryRangeConcat() - это условие 'или'
Кроме того, кто может поручиться, что ранее добавленное условие - это не расширенный фильтр?
__________________
Axapta v.3.0 sp5 kr2 |
|
![]() |
#11 |
Участник
|
ок. убедили.
вариант S.Kuskov: приджойнить exist join тоже не подойдет. поскольку в запросе уже может быть join. http://msdn.microsoft.com/en-us/libr...36(AX.10).aspx тогда остается только перебор записей в случае, если критерий на accountNum установлен? |
|
![]() |
#12 |
Участник
|
похоже вот такой способ будет работать всегда.
но если на код клиента уже был установлен критерий, то этот способ будет работать медленно. X++: boolean findSuperCust(Query _srcQuery, CustAccount _custAccount = "КлиентАБВ") { Query q = new Query(_srcQuery); // создаем копию QueryBuildRange qbr; QueryRun qr; CustTable custTable; // устанавливаем новый критерий только если раньше он был не установлен. qbr = SysQuery::findOrCreateRange(q.dataSourceTable(tablenum(custTable)),fieldnum(custTable, AccountNum)); if( !qbr.value() ) qbr.value(queryValue(_custAccount)); // выполняем запрос qr = new QueryRun(q); while( qr.next() ) { custTable = qr.get(tablenum(CustTable)); if( custTable.accountNum == _custAccount ) return true; } return false; } |
|
![]() |
#13 |
Участник
|
Quote:
X++: boolean findSuperCust(Query _srcQuery, CustAccount _custAccount = "КлиентАБВ") { Query q = new Query(_srcQuery); // создаем копию QueryBuildDataSource qbds = q.dataSourceTable(tablenum(custTable)); QueryBuildRange qbr; QueryRun qr; Range SuperCustRange = strfmt("(%1.%2 == %3)", qbds.name(), fieldStr(custTable, AccountNum)); // устанавливаем новый критерий или меняем существующий qbr = SysQuery::findOrCreateRange(qbds ,fieldnum(custTable, DataAreaId)); if (qbr.value()) qbr.value(strfmt("(%1 && %2)", SuperCustRange, qbr.value())); else qbr.value(SuperCustRange); // выполняем запрос qr = new QueryRun(q); return qr.next(); } |
|
![]() |
#14 |
Участник
|
Quote:
А что, уже стало возможно использовать совместно расширенный синтаксис фильтров и обычный?
__________________
Axapta v.3.0 sp5 kr2 |
|
|
This post has been rated by: S.Kuskov (1). |
![]() |
#15 |
Участник
|
угу.
|
|
![]() |
#16 |
Участник
|
Можно попробовать добавить явный критерий по RecId искомой записи клиента, если он не используется в запросе (обычно не используется
![]() Если используется, то через расширенный фильтр по аналогии с кодом клиента описанной выше у S.Kuskov. Или напрямую распарсить критерии по RecId и либо найти в них искомый и оставить только его либо выдать облом ![]() Last edited by Alexius; 12.09.2011 at 17:32. |
|
![]() |
#17 |
Участник
|
Quote:
Я тут ещё один чисто теоретический способ придумал ![]() Как понятно из обсуждения, основной проблемой является сложность присоединения, в случае уже имеющегося условия, нового контрольного условия по "И". Вот я и подумал раз уж это так проблемно, то пусть оно себе присоединяется по "ИЛИ". В результате исходный запрос изменится и это изменение можно будет анализировать. В случае если количество строк возвращаемое запросом (можно посчитать при помощи SysQuery::countTotal) станется прежним, это будет означать (конечно с определёнными ограничениями), что новое условие по ИЛИ никак не повлияло на выборку, а следовательно исходный запрос содержал в себе контрольное условие. Что и требовалость орпределить ![]() Недостатки: на время анализа вся выборка должна быть заблокирована от корректировок для того чтобы исключить возможность изменения количества строк в запросе из вне. |
|
![]() |
#18 |
Участник
|
Quote:
![]() не, не пойдет |
|
![]() |
#19 |
Участник
|
Quote:
Пользователи его просто не видят в интерфейсе ![]() Кстати, никто не обращал внимание, что критерии со статусом Hidden - не такие уж и невидимые? Достаточно в форме расширенного фильтра вызвать расширенный фильтр (в 2009-й через комбинацию клавишь) и нажать Ok ![]()
__________________
Axapta v.3.0 sp5 kr2 |
|
![]() |
#20 |
Участник
|
Quote:
Quote:
Originally Posted by Владимир Максимов
![]() К сожалению, это ничего не гарантирует. Если исходный запрос относительно сложен и имеет несколько таблиц-источников с "не линейной" схемой объединения, то подключение еще одного источника по Exists Join может привести к тому, что запросу "снесет крышу". Результат может оказаться парадоксальным.
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(); } |
|
|
This post has been rated by: S.Kuskov (1). |
Tags |
query, как правильно |
«
Previous Thread
|
Next Thread
»
|
![]() |
||||
Thread | Replies | |||
Очередной вопрос про Query | 45 | |||
Вопрос по query? | 1 | |||
Вопрос по query и join | 2 | |||
Вопрос по запросу (query) | 2 | |||
Вопрос знатокам QBE и Query в AXAPTA | 6 |
|