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

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 14.10.2009, 10:08   #21  
Bishop is offline
Bishop
Участник
 
89 / 60 (3) ++++
Регистрация: 12.08.2004
Адрес: Москва
А кто-нибудь встречал в стандарте запросы с group by без использования аггрегирующих функций? (не только для временных таблиц, но и для обычных)
Я лично не сталкивался, и всегда думал, что если используешь group by, то добавь хотя бы count(RecId)...
Старый 14.10.2009, 10:19   #22  
lev is offline
lev
Ищущий знания...
Аватар для lev
Oracle
MCBMSS
Axapta Retail User
 
1,723 / 491 (20) +++++++
Регистрация: 18.01.2005
Адрес: Москва
Цитата:
Сообщение от Bishop Посмотреть сообщение
А кто-нибудь встречал в стандарте запросы с group by без использования аггрегирующих функций? (не только для временных таблиц, но и для обычных)
Я лично не сталкивался, и всегда думал, что если используешь group by, то добавь хотя бы count(RecId)...
Ну вообще много где так делается (пример SalesFromLetter::CheckParmTable(), SalesFormLetter_PackingSlip.writeJournalSalesLink() и т.д.)
и я при group by никогда не использую аггрегирующие функции, так как group by сам по себе предполагает вывод только тех полей, которые указаны в нем.
__________________
"Страх перед возможностью ошибки не должен отвращать нас от поисков истины." (с)
С Уважением,
Елизаров Артем
За это сообщение автора поблагодарили: Bishop (1).
Старый 14.10.2009, 10:28   #23  
S.Kuskov is offline
S.Kuskov
Участник
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
 
3,427 / 1771 (66) ++++++++
Регистрация: 28.04.2007
Адрес: Калуга
В связи с отсутствием distinct, использование group by без аггрегирующих функций не такая уж и редкость в Axapta
Старый 14.10.2009, 12:50   #24  
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   #25  
S.Kuskov is offline
S.Kuskov
Участник
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
 
3,427 / 1771 (66) ++++++++
Регистрация: 28.04.2007
Адрес: Калуга
Цитата:
Сообщение от Bishop Посмотреть сообщение
От подобного кода на слое sys становится немного грустно...
А как бы вы сделали?
Старый 14.10.2009, 13:16   #26  
sukhanchik is offline
sukhanchik
Administrator
Аватар для sukhanchik
MCBMSS
Злыдни
Лучший по профессии 2015
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,273 / 3466 (122) ++++++++++
Регистрация: 13.06.2004
Адрес: Москва
Цитата:
Сообщение от Bishop Посмотреть сообщение
От подобного кода на слое sys становится немного грустно...
Ну.. не боги горшки обжигают... даже у буржуев. С одной стороны. А с другой стороны - альтернатива данному коду - есть только через exists join со справочником, что требует дополнительного мыслительного процесса - что за справочник и как он связан.
__________________
Возможно сделать все. Вопрос времени
Старый 14.10.2009, 13:40   #27  
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
Старый 15.10.2009, 12:40   #28  
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   #29  
sukhanchik is offline
sukhanchik
Administrator
Аватар для sukhanchik
MCBMSS
Злыдни
Лучший по профессии 2015
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,273 / 3466 (122) ++++++++++
Регистрация: 13.06.2004
Адрес: Москва
Цитата:
Сообщение от Bishop Посмотреть сообщение
Это была риторическая грусть
Для достижения distinct я пользуюсь двумя глобальными статическими методами:
Ну мне кажется что select просто с group by как бы несколько проще....
__________________
Возможно сделать все. Вопрос времени
Старый 26.10.2009, 15:49   #30  
kashperuk is offline
kashperuk
Участник
Аватар для kashperuk
MCBMSS
Соотечественники
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,361 / 2084 (78) +++++++++
Регистрация: 30.05.2004
Адрес: Atlanta, GA, USA
Цитата:
Сообщение от S.Kuskov Посмотреть сообщение
AX 4.0 SP2

Тестируя отчёт, случайно поймал глюк:
X++:
static void job(Args _args)
{
    tmpTable tmpTable;
    counter cnt;
    ;

    tmpTable.clear();
    tmpTable.Field1 = '1';
    tmpTable.insert();

    tmpTable.clear();
    tmpTable.Field1 = '1';
    tmpTable.insert(); // вставляем две одинаковые строки

    cnt = 0;
    while select tmpTable
    group by Field1
//    where tmpTable.Field1 == '1'
    {
        cnt++;
    }

    info(int2str(cnt));
}
Если раскомментировать предложение WHERE то цикл выполнится 2 раза! У кого-нибудь воспроизводится?

P.S.: Обязательные условия: таблица - временная; поле - текстовое
В АХ 6, похоже, уже это починили.
Старый 14.07.2011, 20:37   #31  
Maximin is offline
Maximin
NavAx
NavAx Club
 
408 / 341 (12) ++++++
Регистрация: 09.10.2002
Адрес: Москва
На 2009 RU6 починили... RU5 не пробовал...
__________________
Жизнь прекрасна! Если, конечно, правильно подобрать антидепрессанты...
Старый 16.01.2015, 10:25   #32  
S.Kuskov is offline
S.Kuskov
Участник
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
 
3,427 / 1771 (66) ++++++++
Регистрация: 28.04.2007
Адрес: Калуга
Цитата:
Сообщение от kashperuk Посмотреть сообщение
В АХ 6, похоже, уже это починили.
Цитата:
Сообщение от Maximin Посмотреть сообщение
На 2009 RU6 починили... RU5 не пробовал...
А как вы проверяли?
Я на AX2009 RU7 сейчас опять наступил на эти грабли. Проверил на AX2012R3 - грабли все ещё там!

Вот видоизменил тестовый джоб, чтобы не нужно было создавать таблицу вручную (используется таблица существующую в стандартном приложении ).
X++:
static void Job_test20150116(Args _args)
{
    TmpABC TmpABC;
    counter cnt;
    ;

    TmpABC.clear();
    TmpABC.ItemId = '1';
    TmpABC.RefRecId = 0;
    TmpABC.doinsert();

    TmpABC.clear();
    TmpABC.ItemId = '1';
    TmpABC.RefRecId = 1;
    TmpABC.doinsert(); // вставляем две одинаковые строки

    cnt = 0;
    while select TmpABC
    group by ItemId
    where TmpABC.ItemId == '1' // !!! с этим условием группировка не выполняется
    {
        info(TmpABC.ItemId); 
        cnt++;
    }

    info(strfmt("Количество итераций цикла: %1", cnt));
}
Теги
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, время: 18:25.
Powered by vBulletin® v3.8.5. Перевод: zCarot
Контактная информация, Реклама.