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

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 29.01.2011, 16:06   #1  
Corel is offline
Corel
Участник
Ex AND Project
 
73 / 15 (1) ++
Регистрация: 19.04.2007
Расширенный диапазон в Query range: вычесть число из даты
Никак не могу побороть один момент в запросе.
Нужно сделать аналог конструкции
X++:
where table1.Date < systemDateGet() - table2.Days
Поначалу было такое, но данные отбирались неверно - видимо, вычитались не дни, а что-то другое (секунды?).
X++:
qbdsTable1.addRange(fieldNum(Table1, Date)).value(
    strfmt('(Date < %1 - %2.%3))',
             date2StrXpp(systemDateGet()),
             query.dataSourceTable(tableNum(Table2)).name(), 
             fieldStr(Table2, Days)));
Думал, использовать SQL - функцию, но идёт постоянная ошибка расширенного диапазона.
X++:
qbdsTable1.addRange(fieldNum(Table1, Date)).value(
    strfmt('(Date < dateadd(%1.%2, -%3.%4, %5))',
             query.dataSourceTable(tableNum(Table1)).name(), 
             fieldStr(Table1, Date),
             query.dataSourceTable(tableNum(Table2)).name(), 
             fieldStr(Table2, Days),
             date2StrXpp(systemDateGet())));
Третий вариант: вычесть из текущей даты значение интересующего поля и сравнить результат с полем во второй таблице тоже не работает, но ошибка уже другая: неверный параметр.

X++:
qbdsTable1.addRange(fieldNum(Table1, Date)).value(
    strfmt('((%1 - %2.%3) > %4.%5)',
             date2StrXpp(systemDateGet()),
             query.dataSourceTable(tableNum(Table1)).name(), 
             fieldStr(Table1, Date),
             query.dataSourceTable(tableNum(Table2)).name(), 
             fieldStr(Table2, Days)));
Старый 29.01.2011, 18:50   #2  
konopello is offline
konopello
SAP
SAP
 
628 / 76 (4) ++++
Регистрация: 08.11.2005
Адрес: Минск
Цитата:
X++:
where table1.Date < systemDateGet() - table2.Days
А почему не вычислить сразу дату:
X++:
date = systemDateGet() - table2.Days
where table1.Date < date
Старый 29.01.2011, 18:57   #3  
greench is offline
greench
Участник
Oracle
 
425 / 74 (3) ++++
Регистрация: 12.07.2007
Адрес: Киев
Пару раз уже сталкивался с подобными штуками. Таки нужное значение лучше вычислить заранее, а потом уже использовать в запросе.
Старый 29.01.2011, 22:50   #4  
Corel is offline
Corel
Участник
Ex AND Project
 
73 / 15 (1) ++
Регистрация: 19.04.2007
Дык, дело-то в том, что это значение получается в результате запроса. Table2 в данном случае - датасорс этого же Query. Иначе и не надо было бы расширенный диапазон заводить.
Старый 30.01.2011, 09:43   #5  
greench is offline
greench
Участник
Oracle
 
425 / 74 (3) ++++
Регистрация: 12.07.2007
Адрес: Киев
Почитайте еще вот эту тему Расширенный запрос по дате
Старый 30.01.2011, 18:42   #6  
Corel is offline
Corel
Участник
Ex AND Project
 
73 / 15 (1) ++
Регистрация: 19.04.2007
Смотрел.
Опять-таки, там не рассматривается поставленная задача. Нужно в условиях для одного датасорса использовать сравнение с полями другого датасорса - задача, давно решаемая с помощью расширенного диапазона.
Проблема именно в том, чтоб задать корректное для вычитание дней из даты в этом расширенном диапазоне.
Старый 31.01.2011, 09:27   #7  
samolalex is offline
samolalex
Участник
Аватар для samolalex
Самостоятельные клиенты AX
 
259 / 107 (4) +++++
Регистрация: 18.06.2010
Адрес: Москва
Цитата:
Нужно в условиях для одного датасорса использовать сравнение с полями другого датасорса - задача, давно решаемая с помощью расширенного диапазона.
Честно говоря, с этим столкнулся впервые.

Может попробовать использовать 1-ый вариант, но с использованием функции date2num():
X++:
qbdsTable1.addRange(fieldNum(Table1, Date)).value(strfmt("date2num(Date) < (date2num(%1) - %2.%3)",
             systemDateGet(),
             query.dataSourceTable(tableNum(Table2)).name(), 
             fieldStr(Table2, Days)));
или так:
X++:
qbdsTable1.addRange(fieldNum(Table1, Date)).value(strfmt("Date < num2date(date2num(%1) - %2.%3)",
             systemDateGet(),
             query.dataSourceTable(tableNum(Table2)).name(), 
             fieldStr(Table2, Days)));
__________________
С уважением, Александр.

Последний раз редактировалось samolalex; 31.01.2011 в 09:33.
Старый 31.01.2011, 10:17   #8  
Corel is offline
Corel
Участник
Ex AND Project
 
73 / 15 (1) ++
Регистрация: 19.04.2007
Ой, что-то вас совсем не туда понесло. Разве в SQL есть функции date2num и num2date?
Это ж, фактически, скулю скармливаться будет. Что он должен делать, получив такое?
X++:
"date2num(Date) < (date2num(%1) - %2.%3)"
Кстати, ошибся при "анонимизанции" кода, пример с SQL функцией выглядит так:
X++:
qbdsTable1.addRange(fieldNum(Table1, Date)).value(
    strfmt('(%1.%2 < dateadd(day, -%1.%2, %5))',
             query.dataSourceTable(tableNum(Table1)).name(), 
             fieldStr(Table1, Date),
             query.dataSourceTable(tableNum(Table2)).name(), 
             fieldStr(Table2, Days),
             date2StrXpp(systemDateGet())));
Правда, всё равно не работает.
Старый 31.01.2011, 10:24   #9  
AndyD is offline
AndyD
Участник
КОРУС Консалтинг
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
 
2,560 / 2476 (88) +++++++++
Регистрация: 20.08.2005
Может, так попробовать
X++:
qbdsTable2.addRange(fieldNum(Table2, Days)).value(
    strfmt('((%1 - %2.%3) > %4)',
             date2StrXpp(systemDateGet()),
             query.dataSourceTable(tableNum(Table1)).name(), 
             fieldStr(Table1, Date),
             fieldStr(Table2, Days)));
__________________
Axapta v.3.0 sp5 kr2
Старый 31.01.2011, 10:53   #10  
pitersky is offline
pitersky
северный Будда
Аватар для pitersky
Ex AND Project
Соотечественники
 
1,486 / 408 (16) +++++++
Регистрация: 26.09.2007
Адрес: Солнечная система
Попробуйте сначала записать в какую-то переменную значение systemDateGet(), а потом в разнице использовать эту переменную
__________________
С уважением,
Вячеслав
Старый 31.01.2011, 11:08   #11  
Corel is offline
Corel
Участник
Ex AND Project
 
73 / 15 (1) ++
Регистрация: 19.04.2007
Цитата:
Сообщение от AndyD Посмотреть сообщение
Может, так попробовать
X++:
qbdsTable2.addRange(fieldNum(Table2, Days)).value(
    strfmt('((%1 - %2.%3) > %4)',
             date2StrXpp(systemDateGet()),
             query.dataSourceTable(tableNum(Table1)).name(), 
             fieldStr(Table1, Date),
             fieldStr(Table2, Days)));
Не, та же фигня - вычитая из своего datetime предлагаемое ему число, скуль всё делает верно. Но он вычитает в единицах этого datetime.
Я сейчас эксперимент поставил: заменил текущую дату на 1 день позже даты записи, которая не должна попадать в запрос и стал менять в table2 кол-во дней, формируя отчёты.
При значении в поле table2.Days 25105 данные, которые не должны попасть в отчёт по этому признаку перестают в него попадать. Но умножением числа дней на 25 тысяч, по-моему, мало что добьюсь - арифметическая ошибка переполнения будет на реальных цифрах.

Цитата:
Сообщение от pitersky Посмотреть сообщение
Попробуйте сначала записать в какую-то переменную значение systemDateGet(), а потом в разнице использовать эту переменную
Смысл? Что функция возвратит дату, которую скуль нормально примет, что переменная - одинаково.

Последний раз редактировалось Corel; 31.01.2011 в 11:14.
Старый 31.01.2011, 11:33   #12  
AndyD is offline
AndyD
Участник
КОРУС Консалтинг
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
 
2,560 / 2476 (88) +++++++++
Регистрация: 20.08.2005
Прошу прощение за настойчивость, но вы обратили внимание, что рейнж накладывается на поле не первого, а второго датасорса?

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

Вот так это условие отправляется на сервер
{ts '2011-01-31 00:00:00.000'}-A.INVOICEDATE)<=B.RECVERSION

Не судите за корректность запроса, это только проверка
Миниатюры
Нажмите на изображение для увеличения
Название: Запрос.png
Просмотров: 1510
Размер:	24.6 Кб
ID:	6536  
__________________
Axapta v.3.0 sp5 kr2
Старый 31.01.2011, 11:58   #13  
Corel is offline
Corel
Участник
Ex AND Project
 
73 / 15 (1) ++
Регистрация: 19.04.2007
Цитата:
Сообщение от AndyD Посмотреть сообщение
Прошу прощение за настойчивость, но вы обратили внимание, что рейнж накладывается на поле не первого, а второго датасорса?
Эээ... не обратил.
Хм... Попробую так. Если у вас вычитание даты из даты корректно работает, значит, надежда есть.

Upd:
Попробовал. Ошибка расширенного диапазона:
Ошибка расширенного диапазона запроса: Table1.Date не является корректной парой datasource.field рядом с 45.
Видимо, из-за того, что датасорсы уж очень далеко отстоят друг от друга - table2 входит в запрос гораздо выше.

Сейчас пробую так:
делаю предварительный запрос, собрав в Map интересующие меня пары код - кол-во дней из table2, а затем в основном Query иду по этой мапе и ставлю условие

X++:
qbdsTable1.addRange(fieldNum(Table1, Date)).value(strfmt('((%2.%4 == %5) && (%6.%7 < %1))',
    date2StrXpp(systemDateGet() - any2int(mapIterator.value())), //%1
    query.dataSourceTable(tableNum(Table2)).name(),                //%2
    fieldStr(Table2, Days),                                                         //%3
    fieldStr(Table2, Id),                                                              //%4
    SysQuery::value(mapIterator.key()),                                      //%5
    query.dataSourceTable(tableNum(Table1)).name(),                 //%6
    fieldStr(Table1, Date)));                                                        //%7
Но пока что выдаёт в это месте синтаксическую ошибку рядом с 38.

Последний раз редактировалось Corel; 31.01.2011 в 12:23.
Старый 31.01.2011, 12:38   #14  
AndyD is offline
AndyD
Участник
КОРУС Консалтинг
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
 
2,560 / 2476 (88) +++++++++
Регистрация: 20.08.2005
Ну, по идее, это должно и в обратную строну работать
X++:
qbdsTable1.addRange(fieldNum(Table1, Date)).value(
    strfmt('((%1 - %2) > %3.%4)',
             date2StrXpp(systemDateGet()),
             fieldStr(Table1, Date),
             query.dataSourceTable(tableNum(Table2)).name(), 
             fieldStr(Table2, Days)));
Хотя, вы бы привели запрос полностью, что бы было видно, как таблицы между собой соединяются
__________________
Axapta v.3.0 sp5 kr2
Старый 31.01.2011, 14:28   #15  
Corel is offline
Corel
Участник
Ex AND Project
 
73 / 15 (1) ++
Регистрация: 19.04.2007
Цитата:
Сообщение от AndyD Посмотреть сообщение
Ну, по идее, это должно и в обратную строну работать
По идее-то да. Но вот в таком варианте наблюдаю вываливание на QueryRun.next() в тарссировку стека с ошибкой "неверный параметр".

Цитата:
Хотя, вы бы привели запрос полностью, что бы было видно, как таблицы между собой соединяются
Ок. Убрал из запроса лишнее, Table1 - это InventTrans.
Запрос должен находить номенклатуры, относящиеся к выбранным Table2 (на Table2 накладывается пользовательский фильтр), у которых текущие остатки больше 0 и по которым есть приходные проводки с датой раньше, чем текущая минус кол-во дней, указанное в соответствующей Table2.
X++:
    query = new Query();
    qbdsTable2 = query.addDataSource(tableNum(Table2));
    qbdsInventTable = qbdsTable2.addDataSource(tableNum(InventTable));
    qbdsInventTable.addLink(fieldNum(Table2, Id), fieldNum(InventTable, Table2Id));
    qbdsInventTable.addGroupByField(fieldNum(InventTable, ItemId));
    qbdsInventSum = qbdsInventTable.addDataSource(tableNum(InventSum));
    qbdsInventSum.relations(true);
    qbdsInventSum.addRange(fieldNum(InventSum, PostedQty)).value('(PostedQty>0)');
    qbdsInventSum.addSelectionField(fieldNum(InventSum, PostedQty), SelectionField::Sum);
    qbdsInventTrans = qbdsInventSum.addDataSource(tableNum(InventTrans));
    qbdsInventTrans.relations(true);
    qbdsInventTrans.addRange(fieldNum(InventTrans, StatusReceipt)).value(queryValue(StatusReceipt::Purchased));
    qbdsInventTrans.addRange(fieldNum(InventTrans, DateFinancial)).value(strfmt('(((%1 - %2) > %3.%4))',
                                                                                 date2StrXpp(systemDateGet()),
                                                                                 fieldStr(InventTrans, DateFinancial),
                                                                                 query.dataSourceTable(tableNum(Table2)).name(),
                                                                                 fieldStr(Table2, Days)));
    qbdsInventTrans.joinMode(JoinMode::ExistsJoin);
Старый 31.01.2011, 15:24   #16  
PavelX is offline
PavelX
MCTS
MCBMSS
 
46 / 97 (4) ++++
Регистрация: 08.09.2006
Адрес: Красноярск
Цитата:
Сообщение от Corel Посмотреть сообщение
Ошибка расширенного диапазона запроса: Table1.Date не является корректной парой datasource.field рядом с 45.
Похожие ошибки бывают когда накладываемое значение ренджа очень длинное и попросту обрезается парсером (вроде в рендж входит значение не длиннее 255 символов). Хотя в Вашем случае условие и не выглядит длинным, но мало ли...
Старый 31.01.2011, 17:13   #17  
Alexius is offline
Alexius
Участник
Аватар для Alexius
 
461 / 248 (9) ++++++
Регистрация: 13.12.2001
А такой вариант ?
X++:
    qbdsInventTrans.addRange(fieldNum(InventTrans, DateFinancial)).value(strfmt('(((%1.%2 + %3.%4 - %5) > 0))',
                                                                                 query.dataSourceTable(tableNum(InventTrans)).name(),
                                                                                 fieldStr(InventTrans, DateFinancial),
                                                                                 query.dataSourceTable(tableNum(Table2)).name(),
                                                                                 fieldStr(Table2, Days),
                                                                                 date2StrXpp(systemDateGet()));
Старый 31.01.2011, 17:28   #18  
Corel is offline
Corel
Участник
Ex AND Project
 
73 / 15 (1) ++
Регистрация: 19.04.2007
Цитата:
Сообщение от Alexius Посмотреть сообщение
А такой вариант ?
X++:
    qbdsInventTrans.addRange(fieldNum(InventTrans, DateFinancial)).value(strfmt('(((%1.%2 + %3.%4 - %5) > 0))',
                                                                                 query.dataSourceTable(tableNum(InventTrans)).name(),
                                                                                 fieldStr(InventTrans, DateFinancial),
                                                                                 query.dataSourceTable(tableNum(Table2)).name(),
                                                                                 fieldStr(Table2, Days),
                                                                                 date2StrXpp(systemDateGet()));
Не-не-не... Не получится никак заставить SQL прибавлять / вычитать из даты дни так, как аксапта это делает с типом Date, т.к. в SQL это поле имеет формат DateTime. Это будет сложение километров с милиметрами. Кстати, похоже, и вычитание даты из даты тоже даёт эффект только при сравнении с нулём, то есть, в таком случае можно просто свести к сравнению. Ищу, где же косяк в варианте с предварительно составленным мапом, может скобку где пропустил...

Последний раз редактировалось Corel; 31.01.2011 в 17:32.
Старый 31.01.2011, 17:29   #19  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1152 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Записей в блоге: 19
Цитата:
Сообщение от PavelX Посмотреть сообщение
Похожие ошибки бывают когда накладываемое значение ренджа очень длинное и попросту обрезается парсером (вроде в рендж входит значение не длиннее 255 символов)
Стандартно - 250. И это стандартный размер EDT Range (Позиционирование в гриде). И только в том случае, если пользователю предъявляется форма параметров запроса, т.е. вызывается queryRun.prompt(). Если всё происходит только невидимо в коде, то размер строки Range практически не ограничен (может быть, 64К ?).
За это сообщение автора поблагодарили: PavelX (1), Corel (1).
Старый 31.01.2011, 17:42   #20  
Alexius is offline
Alexius
Участник
Аватар для Alexius
 
461 / 248 (9) ++++++
Регистрация: 13.12.2001
Цитата:
Сообщение от Corel Посмотреть сообщение
Не-не-не... Не получится никак заставить SQL прибавлять / вычитать из даты дни так, как аксапта это делает с типом Date, т.к. в SQL это поле имеет формат DateTime.
Не понимаю, следующий запрос на MS SQL корректно отрабатывает, т.е. вторая дата на один день меньше (для Oracle должно быть аналогично):
Код:
SELECT TOP 1 DATEFINANCIAL, DATEFINANCIAL - 1
FROM INVENTTRANS
WHERE DATEFINANCIAL <> '19000101'
PS. Неплохо бы отслеживать профайлером результирующий запрос
PS2. Городить полноценный полигон мне лень
Теги
querybuildrange, дата, расширенный фильтр

 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
axaptafreak: Label for query range cannot be modified in AX 5.0 Blog bot DAX Blogs 0 30.08.2007 16:50
axaptafreak: Label for Query Range cannot be modified (still) Blog bot DAX Blogs 2 25.07.2007 10:09
Fred Shen: Date data type in Query Range Value Expression Blog bot DAX Blogs 0 28.10.2006 16:40
Автоматическая подстановка Range в Query Владимир Максимов DAX: Программирование 9 30.03.2004 16:48
Как вытащить информацию о Range из Query raz DAX: База знаний и проекты 1 26.03.2004 11:10

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

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

Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 09:28.
Powered by vBulletin® v3.8.5. Перевод: zCarot
Контактная информация, Реклама.