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

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 14.10.2009, 12:50   #1  
Bishop is offline
Bishop
Участник
 
89 / 60 (3) ++++
Регистрация: 12.08.2004
Адрес: Москва
Цитата:
Сообщение от lev Посмотреть сообщение
Ну вообще много где так делается (пример SalesFromLetter::CheckParmTable(), SalesFormLetter_PackingSlip.writeJournalSalesLink() и т.д.)
и я при group by никогда не использую аггрегирующие функции, так как group by сам по себе предполагает вывод только тех полей, которые указаны в нем.
SalesFromLetter::checkParmTable()
X++:
        while select salesParmT
                group by CustAccount
                where salesParmT.ParmId == parmId
        {
            numOfAccounts += 1;
        }
От подобного кода на слое sys становится немного грустно...
Старый 14.10.2009, 12:54   #2  
S.Kuskov is offline
S.Kuskov
Участник
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
 
3,440 / 1775 (66) ++++++++
Регистрация: 28.04.2007
Адрес: Калуга
Цитата:
Сообщение от Bishop Посмотреть сообщение
От подобного кода на слое sys становится немного грустно...
А как бы вы сделали?
Старый 15.10.2009, 12:40   #3  
Bishop is offline
Bishop
Участник
 
89 / 60 (3) ++++
Регистрация: 12.08.2004
Адрес: Москва
Цитата:
Сообщение от S.Kuskov Посмотреть сообщение
Цитата:
Сообщение от Bishop
От подобного кода на слое sys становится немного грустно...
А как бы вы сделали?
Это была риторическая грусть
Для достижения distinct я пользуюсь двумя глобальными статическими методами:
1) notexists join на эту же таблицу - позволяет получить кол-во различных значений по группе полей, так же работает со временными таблицами, неприменим для таблиц с большим количеством строк (если не использовать доп. критерии), так как запрос вызывает на sql-сервере сущий ад...
X++:
// Возвращает кол-во различных значений заданного набора полей таблицы
// Формируется запрос:
#if.never
    select count(RecId) from table
        where
            table.FieldRange1   == value1       &&  // доп. условия
            ...
    notexists join tableNE                          // tableNE.TableId = table.TableId
        where
            tableNE.RecId       <  table.RecId  &&  // основная идея
            tableNE.Field1      == table.Field1 &&  // набор полей
            ...                                 &&
            tableNE.FieldRange1 == value1       &&  // доп. условия
            ...
#endif
static counter distinctValues(
    TableId     _tableId,               // код таблицы
    container   _conFields,             // перечень полей
    container   _conRanges  = connull(),// перечень критериев [fieldId, range, ...]
    Common      _tmpCommon  = null      // временная таблица
    )
{
    DictTable               dictTable;
    Common                  common;
    Common                  commonNE;
    Query                   query;
    QueryBuildDataSource    qbds, qbdsNE;
    QueryRun                queryRun;
    int                     i;
    ;
    query = new Query();
    qbds = query.addDataSource(_tableId, "ds1");
    qbds.orderMode(OrderMode::GroupBy);
    qbds.addSelectionField(fieldNum(Common, RecId), SelectionField::Count);
    for (i = 1; i <= conlen(_conRanges) div 2; i+=2)
    {
        qbds.addRange(conpeek(_conRanges, i)).value(conpeek(_conRanges, i+1));
    }
    qbdsNE = qbds.addDataSource(_tableId, "ds2");
    qbdsNE.joinMode(JoinMode::NoExistsJoin);
    qbdsNE.addRange(fieldNum(Common, RecId)).value("((ds2.RecId < ds1.RecId))");
    for (i = 1; i <= conlen(_conFields); i++)
    {
        qbdsNE.addLink(conpeek(_conFields, i), conpeek(_conFields, i));
    }
    for (i = 1; i <= conlen(_conRanges) div 2; i+=2)
    {
        qbdsNE.addRange(conpeek(_conRanges, i)).value(conpeek(_conRanges, i+1));
    }
    queryRun = new QueryRun(query);
    if (_tmpCommon)
    {
        dictTable   = new DictTable(_tableId);
        common      = dictTable.makeRecord();
        commonNE    = dictTable.makeRecord();
        common.setTmpData(_tmpCommon);
        commonNE.setTmpData(_tmpCommon);
        queryRun.setCursor(common, 1);
        queryRun.setCursor(commonNE, 2);
    }
    queryRun.next();
    return queryRun.getNo(1).RecId;
}
2) Прямой запрос на sql-сервер. Не работает со временными таблицами и ограничивает получение различных значений только по одному полю
X++:
// Возвращает кол-во различных значений заданного поля таблицы
/* Выполняется sql-запрос:
SELECT COUNT (DISTINCT Field) FROM Table WHERE ...
*/
server static counter distinctValuesDirect(
    TableId     _tableId,               // код таблицы
    FieldId     _fieldId,               // код поля
    container   _conRanges = connull()  // перечень критериев [fieldId, range, ...]
    )
{
    DictTable       dictTable = new DictTable(_tableId);
    ResultSet       resultSet;
    SqlSystem       sqlSystem = new SqlSystem();
    str             sql;
    str             rangeList;
    int             i;
    ;
    if (dictTable.dataPrCompany())
    {
        rangeList = strfmt(" where %1 = %2",
            dictTable.fieldName(fieldNum(Common, DataAreaId), DbBackend::Sql),
            sqlSystem.sqlLiteral(curext()) );
    }
    for (i = 1; i <= conlen(_conRanges) div 2; i+=2)
    {
        rangeList = (rangeList ? "" : " where ") + rangeList + (rangeList ? " and " : "") +
            strfmt("%1 = %2",
                dictTable.fieldName(conpeek(_conRanges, i), DbBackend::Sql),
                sqlSystem.sqlLiteral(conpeek(_conRanges, i+1)) );
    }
    sql = strfmt("select count (distinct %1) from %2%3",
        dictTable.fieldName(_fieldId, DbBackend::Sql),
        dictTable.name(DbBackend::Sql),
        rangeList);
    new SqlStatementExecutePermission(sql).assert();
    resultSet = new Connection().createStatement().executeQuery(sql);
    CodeAccessPermission::revertAssert();
    if (resultSet.next())
    {
        return resultSet.getInt64(1);
    }
    return 0;
}
За это сообщение автора поблагодарили: sukhanchik (1), S.Kuskov (1).
Старый 15.10.2009, 12:58   #4  
sukhanchik is offline
sukhanchik
Administrator
Аватар для sukhanchik
MCBMSS
Злыдни
Лучший по профессии 2015
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,322 / 3547 (125) ++++++++++
Регистрация: 13.06.2004
Адрес: Москва
Цитата:
Сообщение от Bishop Посмотреть сообщение
Это была риторическая грусть
Для достижения distinct я пользуюсь двумя глобальными статическими методами:
Ну мне кажется что select просто с group by как бы несколько проще....
__________________
Возможно сделать все. Вопрос времени
Старый 14.10.2009, 13:16   #5  
sukhanchik is offline
sukhanchik
Administrator
Аватар для sukhanchik
MCBMSS
Злыдни
Лучший по профессии 2015
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,322 / 3547 (125) ++++++++++
Регистрация: 13.06.2004
Адрес: Москва
Цитата:
Сообщение от Bishop Посмотреть сообщение
От подобного кода на слое sys становится немного грустно...
Ну.. не боги горшки обжигают... даже у буржуев. С одной стороны. А с другой стороны - альтернатива данному коду - есть только через exists join со справочником, что требует дополнительного мыслительного процесса - что за справочник и как он связан.
__________________
Возможно сделать все. Вопрос времени
Старый 14.10.2009, 13:40   #6  
ZVV is offline
ZVV
MCITP
MCP
Oracle
MCBMSS
 
1,006 / 246 (11) ++++++
Регистрация: 13.02.2004
Адрес: Минск
->
Цитата:
Сообщение от Bishop Посмотреть сообщение
SalesFromLetter::checkParmTable()
X++:
        while select salesParmT
                group by CustAccount
                where salesParmT.ParmId == parmId
        {
            numOfAccounts += 1;
        }
От подобного кода на слое sys становится немного грустно...
Ну альтернативы то:
либо то что тут,
либо как сказали выше (и на ссылке выше тоже есть пример), делать экзист со справочником...
Тоже не шибко всё красиво...
__________________
Zhirenkov Vitaly
Теги
bug, баг, временная таблица, запрос (query), ошибка

 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
Временная таблица Antoncheg DAX: Программирование 21 15.08.2008 18:25
производительность: map или временная таблица kitty DAX: Программирование 5 15.11.2007 12:36
Временная таблица + RLS leshy DAX: Программирование 6 27.04.2006 12:39
select sum(amount) from временная таблица ATimTim DAX: Программирование 6 11.06.2004 14:16
next и временная таблица Dron AKA andy DAX: Программирование 3 24.04.2003 16:42

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

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

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