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

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 29.01.2009, 17:03   #1  
S.Kuskov is offline
S.Kuskov
Участник
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
 
3,437 / 1775 (66) ++++++++
Регистрация: 28.04.2007
Адрес: Калуга
! Порядок выполнения GroupBy и Exists Join для временных таблиц
Как должна выполнятся конструкция вида
X++:
    while select tmpTable1
    group by GroupId
    exists join tmpTable2
    where
         tmpTable2.Id == tmpTable1.Id
?

По аналогии с постоянными таблицами можно предположить, что сначала из таблицы tmpTable1 выберутся строкии, Id которых соответствуют строкам из таблицы tmpTable2. И затем отобранные строки сгруппируются по полю GroupId.

На практике же оказывается что group by отрабатывает первым. Причём значение поля id не обнуляется, а становится равным значению из первой строки группы (первой по очерёдности вставки). И вот уже с этими Id продолжает работать exists join. Естественно результат такой выборки мало предсказуем.

Данный баг уже был описан ранее? Или это фича такая?
Старый 29.01.2009, 21:13   #2  
sukhanchik is offline
sukhanchik
Administrator
Аватар для sukhanchik
MCBMSS
Злыдни
Лучший по профессии 2015
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,307 / 3540 (125) ++++++++++
Регистрация: 13.06.2004
Адрес: Москва
Может я конечно чего-то не догоняю, но Вы видимо ожидаете увидеть поле GroupId пустым? В Аксапте контсрукция типа
X++:
select tmpTable1
    group by GroupId
полностью аналогична конструкции
X++:
select GroupId from tmpTable1
    group by GroupId
и это надо учитывать. А SQL запрос в БД нельзя построить так, чтобы не выводились поля, которые есть в группировке.

И потом - описанная Вами конструкция преобразуется в SQL вида
X++:
SELECT GROUPID FROM TMPTABLE1
WHERE TMPTABLE1.GROUPID EXISTS IN (SELECT * FROM TMPTABLE2 WHERE TMPTABLE2.GROUPID = TMPTABLE1.GROUPID)
GROUP BY GROUPID
т.е. это не JOIN и поэтому каждый SELECT выполняется как бы последовательно (образно выражаясь)
__________________
Возможно сделать все. Вопрос времени
Старый 29.01.2009, 22:34   #3  
S.Kuskov is offline
S.Kuskov
Участник
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
 
3,437 / 1775 (66) ++++++++
Регистрация: 28.04.2007
Адрес: Калуга
в моём примере запрос имеет немного другой вид
Код:
SELECT GROUPID FROM TMPTABLE1
WHERE TMPTABLE1.GROUPID EXISTS IN (SELECT * FROM TMPTABLE2 WHERE TMPTABLE2.ID = TMPTABLE1.ID)
GROUP BY GROUPID
т.е. связь со второй таблицей по полю "Id". И главная проблема в том что если таблицы tmpTable1 и tmpTable2 являются временными, то результат отличен от предпологаемого. Он скорее становится похож на следующую структуру
Код:
SELECT T.GROUPID FROM (SELECT GROUPID, MIN(ID) FROM TMPTABLE1 GROUP BY GROUPID) AS T WHERE EXISTS(SELECT * FROM TMPTABLE2 WHERE TMPTABLE2.ID = T.ID)
Разница, согласитесь, существенная
Старый 29.01.2009, 23:16   #4  
sukhanchik is offline
sukhanchik
Administrator
Аватар для sukhanchik
MCBMSS
Злыдни
Лучший по профессии 2015
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,307 / 3540 (125) ++++++++++
Регистрация: 13.06.2004
Адрес: Москва
А, я понял. Дело в том, что Аксапта сама не генерит JOIN-конструкции. А без JOIN-конструкции нельзя будет связать как Вы хотите - до группировки. При этом, замечу, что группировка заведомо предполагает перечисление в явном виде полей для выборки (чего кстати говоря нет в Вашем исходном примере у 2-й таблицы) и группировки.
Пример, который я написал про SQL-запрос намеренно написан именно так. Ваш вариант
PHP код:
SELECT GROUPID FROM TMPTABLE1
WHERE TMPTABLE1
.GROUPID EXISTS IN (SELECT FROM TMPTABLE2 WHERE TMPTABLE2.ID TMPTABLE1.ID)
GROUP BY GROUPID 
некорректен - т.к. конструкция SELECT * FROM TMPTABLE2 WHERE TMPTABLE2.ID = TMPTABLE1.ID не отработает из-за отсутствия в списке для выборки (а значит и группировки) из 1-й таблицы поля ID (группировка будет наложена раньше связывания).

PS. Теперь окончательно понял Т.е. конструкция самого запроса принципиально меняется. Это конечно интересно проверить. Однако - дело в том, что временные таблицы не всегда джойнятся с группировкой как у Вас, да еще связываясь по полю, не участвующему в группировке. В системе часто используются всякие Map, Set, RecordSortedList и прочие конструкции, торчащие в памяти (в частности при разноске). Временная таблица как правило нужна, чтобы в нее запихнуть конкретные данные для вывода в форму/отчет. И джойнить с ней подразумевается только справочники (т.е. без группировок и exists join). Конечно наверняка найдутся примеры и такого использования кода, но....сначала было бы неплохо их глянуть - чтобы понять где они есть и отрабатывают ли они вообще в России (т.к. форум в основном используется людьми, использующих российскую локализацию).
__________________
Возможно сделать все. Вопрос времени
Старый 30.01.2009, 08:09   #5  
S.Kuskov is offline
S.Kuskov
Участник
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
 
3,437 / 1775 (66) ++++++++
Регистрация: 28.04.2007
Адрес: Калуга
Вот набрасал небольшой пример
X++:
static void TEST_Job(Args _args)
{
    TEST_tmpTable1 TEST_tmpTable1;
    TEST_tmpTable2 TEST_tmpTable2;
    ;

    //-----------------------------------------------
    TEST_tmpTable1.GroupId = '01';
    TEST_tmpTable1.Id = 1; TEST_tmpTable1.insert();
    TEST_tmpTable1.Id = 2; TEST_tmpTable1.insert();
    TEST_tmpTable1.GroupId = '02';
    // Но если следующие две строки кода поменять местами,
    // то результат будет другой
    TEST_tmpTable1.Id = 4; TEST_tmpTable1.insert();
    TEST_tmpTable1.Id = 3; TEST_tmpTable1.insert();

    TEST_tmpTable2.Id = 1; TEST_tmpTable2.insert();
    TEST_tmpTable2.Id = 3; TEST_tmpTable2.insert();
    //-----------------------------------------------

    while select TEST_tmpTable1
    group by GroupId
    exists join TEST_tmpTable2
    where
        TEST_tmpTable2.Id == TEST_tmpTable1.Id
    {
        info(TEST_tmpTable1.GroupId);
    }
}
Вложения
Тип файла: xpo SharedProject_Project_TEST_20090129_m01.xpo (3.7 Кб, 572 просмотров)

Последний раз редактировалось S.Kuskov; 30.01.2009 в 08:21.
Старый 30.01.2009, 09:06   #6  
S.Kuskov is offline
S.Kuskov
Участник
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
 
3,437 / 1775 (66) ++++++++
Регистрация: 28.04.2007
Адрес: Калуга
Цитата:
Сообщение от sukhanchik Посмотреть сообщение
Ваш вариант
PHP код:
SELECT GROUPID FROM TMPTABLE1
WHERE TMPTABLE1
.GROUPID EXISTS IN (SELECT FROM TMPTABLE2 WHERE TMPTABLE2.ID TMPTABLE1.ID)
GROUP BY GROUPID 
некорректен - т.к. конструкция SELECT * FROM TMPTABLE2 WHERE TMPTABLE2.ID = TMPTABLE1.ID не отработает из-за отсутствия в списке для выборки (а значит и группировки) из 1-й таблицы поля ID (группировка будет наложена раньше связывания).
В том то и дело, что корректен, но только для постоянных таблиц. Т.е. SQL Server всё делает в правильном (ожидаемом) порядке. Сначала Exists, а уже потом Group by. Когда же дело доходит до временных таблиц, то тут Axapta всё берёт в свои руки и делает это, мягко говоря, не очень
Старый 06.12.2012, 16:55   #7  
S.Kuskov is offline
S.Kuskov
Участник
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
 
3,437 / 1775 (66) ++++++++
Регистрация: 28.04.2007
Адрес: Калуга
Сейчас проверил на AX2012 порядок работы для постоянных и временных(InMemory) таблиц попрежнему отличается
Теги
bug, баг, временная таблица, запрос (query), ошибка

 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
Проблемы с Exists Join Logger DAX: Программирование 28 28.04.2010 02:54
Данные в Grid из таблиц, связанных по Outer Join cherv DAX: Программирование 2 17.02.2007 01:36
Проблема с Exists Join Morpheus DAX: Программирование 5 14.08.2006 18:22
outer join для трех таблиц r25 DAX: Программирование 4 29.04.2004 15:42

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

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

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