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

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 15.01.2008, 15:23   #1  
Starling is offline
Starling
Участник
Дети Юза
 
530 / 76 (4) ++++
Регистрация: 20.10.2005
Адрес: Kiev
Взаимоисключающие условия для like
Исходные данные задачи:
1. Есть Table1 c полями:
a. Id – код
b. Amount – сумма
2. Есть периодическая операция, которая должна выбрать записи из table1 и увеличить значение поля Amount на заданную величину. При запуске операции открывается временная таблица tmpTable1, с полями:
a. Mask – маска для поля id в Table1
b. addAmount – величина , на которую необходимо увеличить значение в поле Amount в Table1
Т.е. примерно такой код:
X++:
While select from tmpTable1
	Join forUpdate  Table1 where Table1.Id like tmpTable1.Mask
{
	Table1.Amount += tmpTable1.addAmount;
	Table1.update();
}
Вопрос – как реализовать проверку, чтобы значение в поле mask таблицы tmpTable1 были взаимоисключающими, т.е. чтобы одно значение Id в Table1 удовлетворяло только одной (или ни одной) записи в tmpTable1.
Пример:
Вариант 1 (корректный) - когда одна запись из table1 может быть сджойнена только с одной записью tmpTable1
Mask1 = 6*
Mask2 = 7*
Вариант2 (некорректный) - когда одна запись из table1 может быть с джойнена c несколькими записями tmpTable1
Mask1 = 6*
Mask2 = *7
Старый 15.01.2008, 15:44   #2  
George Nordic is offline
George Nordic
Модератор
Аватар для George Nordic
Злыдни
 
4,479 / 1250 (50) ++++++++
Регистрация: 17.12.2003
Адрес: Moscow
Записей в блоге: 9
Почитайте про outter, exists и про innerjoin.

Справка по select

С Уважением,
Георгий
Старый 15.01.2008, 15:49   #3  
NNB is offline
NNB
Участник
 
103 / 12 (1) ++
Регистрация: 31.08.2006
То есть Вам надо обнаружить наличие двух строчек с одним id из tabl1. Если это так то в томи же цикле и проверяйте очевидным образом
Старый 15.01.2008, 15:54   #4  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1152 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Записей в блоге: 19
Цитата:
Сообщение от Starling Посмотреть сообщение
Пример:
Вариант 1 (корректный) - когда одна запись из table1 может быть сджойнена только с одной записью tmpTable1
Mask1 = 6*
Mask2 = 7*
Вариант2 (некорректный) - когда одна запись из table1 может быть с джойнена c несколькими записями tmpTable1
Mask1 = 6*
Mask2 = *7
Может, покажете для примера несколько конкретных значений из каждой таблицы и что чему должно соответствовать? А то так "на слух" тяжеловато соображается... Спасибо.

P.S. Насколько я понимаю, при условиях варианта 1 значение, например, 67 однозначно попадет на 6*, а при условиях варианта 2 значению 67 будут соответствовать и 6*, и *7, что недопустимо. А чему из двух должно однозначно соответствовать 67 во втором случае? Т.е. какие "правила игры"?
Старый 15.01.2008, 16:05   #5  
Starling is offline
Starling
Участник
Дети Юза
 
530 / 76 (4) ++++
Регистрация: 20.10.2005
Адрес: Kiev
Пример1 (корректный):
Записи table1
7489 +10
7569 +11
6758 +12
6547 +13
Записи tmpTable1:
7* +2
6* +3
После выполнения получу такие данные в table1
7489 +12 (+2 по маске 7*)
7569 +13 (+2 по маске 7*)
6758 +15 (+3 по маске 6*)
6547 +16 (+3 по маске 6*)
Пример2 (некорректный по БП):
Записи table1
7489 +10
7569 +11
6758 +12
6547 +13
Записи tmpTable1:
*7 +2
6* +3
После выполнения получу такие данные в table1
7489 10 (0 нет подходящей маски)
7569 11 (0 нет подходящей маски)
6758 15 (+3 по маске 6*)
6547 18 (+3 по маске 6* и +2 по маске *7) – возможность появления таких ситуаций я хочу исключить, выполнив проверку данных в таблице tmpTable1.
Старый 15.01.2008, 16:10   #6  
Starling is offline
Starling
Участник
Дети Юза
 
530 / 76 (4) ++++
Регистрация: 20.10.2005
Адрес: Kiev
Цитата:
Сообщение от Gustav Посмотреть сообщение
А чему из двух должно однозначно соответствовать 67 во втором случае? Т.е. какие "правила игры"?
Для 67 должно быть только одно подходящее условие, если их 2 - это уже некорреткно.
Старый 15.01.2008, 16:17   #7  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1152 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Записей в блоге: 19
Цитата:
Сообщение от Starling Посмотреть сообщение
Для 67 должно быть только одно подходящее условие, если их 2 - это уже некорреткно.
Это уже понятно, но приоритет-то Вами каким-то образом должен быть задан. Я и спрашиваю про "правила"
Старый 15.01.2008, 16:24   #8  
Starling is offline
Starling
Участник
Дети Юза
 
530 / 76 (4) ++++
Регистрация: 20.10.2005
Адрес: Kiev
Цитата:
Сообщение от Gustav Посмотреть сообщение
Это уже понятно, но приоритет-то Вами каким-то образом должен быть задан. Я и спрашиваю про "правила"
Правила игры одно – если в таблице tmpTable1 есть хотябы 2 записи, которым потенциально может удовлетворять одно и тоже значение id из таблицы table1, то это ошибка. Если таких записей нет, то и ошибки нет.
Старый 15.01.2008, 16:28   #9  
dn is offline
dn
Участник
Самостоятельные клиенты AX
 
486 / 159 (6) ++++++
Регистрация: 26.03.2003
Адрес: Москва
Цитата:
Сообщение от Starling Посмотреть сообщение
6547 18 (+3 по маске 6* и +2 по маске *7) – возможность появления таких ситуаций я хочу исключить, выполнив проверку данных в таблице tmpTable1.
Заводим переменную, куда пишем значение приращения по маске, если значение этой переменной было 0. При переходе к новой записи в table1 значение этой переменной обнуляем. Если проверка на 0 не сработала, то откатываем приращение по этой строке.
Старый 15.01.2008, 16:35   #10  
Starling is offline
Starling
Участник
Дети Юза
 
530 / 76 (4) ++++
Регистрация: 20.10.2005
Адрес: Kiev
Цитата:
Сообщение от dn Посмотреть сообщение
Заводим переменную, куда пишем значение приращения по маске, если значение этой переменной было 0. При переходе к новой записи в table1 значение этой переменной обнуляем. Если проверка на 0 не сработала, то откатываем приращение по этой строке.
Это коночно решение, но решение полным перебором по ходу выполнения операции. Мне бы хотелось решить эту проверку одним запросом, и при этом не обращаясь к таблице table1.
Можно конечно написать что-то типа:
X++:
select firstOnly from table1
        join tmpTable1 
            where table1.id like tmpTable1.mask
        join tmpTable2 
            where table1.id like tmpTable2.mask &&
                  tmpTable1.recId != tmpTable2.recId;
И если table1 будет найдено, то ошибка.
А как это сделать не обращаясь к table1?
Старый 15.01.2008, 16:39   #11  
belugin is offline
belugin
Участник
Аватар для belugin
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,622 / 2925 (107) +++++++++
Регистрация: 16.01.2004
Записей в блоге: 5
Может так сойдет?
X++:
Set updated = new Set(Types::Int64);
While select from tmpTable1
	Join forUpdate  Table1 where Table1.Id like tmpTable1.Mask
{
      if (!updated.in(Table1.RecID))
     {              
              Table1.Amount += tmpTable1.addAmount;
              Table1.update();
              updated.add(Table1.RecID)
      }
}

Последний раз редактировалось belugin; 15.01.2008 в 16:41.
Старый 15.01.2008, 16:40   #12  
Starling is offline
Starling
Участник
Дети Юза
 
530 / 76 (4) ++++
Регистрация: 20.10.2005
Адрес: Kiev
вот такой запрос:
X++:
select firstOnly tmpTable1
        join tmpTable2
            where tmpTable2.Mask like tmpTable1.Mask &&
                      tmpTable2.RecId != tmpTable1.RecId;
работать не желает. Я так понимаю потому, что в like можно использовать маску только в правом аргументе
Старый 15.01.2008, 16:44   #13  
Starling is offline
Starling
Участник
Дети Юза
 
530 / 76 (4) ++++
Регистрация: 20.10.2005
Адрес: Kiev
Если в таблице tmpTable1 есть хотябы 2 записи, которым потенциально может удовлетворять одно и тоже значение id из таблицы table1, то это ошибка и обновлять table1 не нужно.

to belugin
Ну это почти тоже самое, что предложил dn
Старый 15.01.2008, 17:05   #14  
belugin is offline
belugin
Участник
Аватар для belugin
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,622 / 2925 (107) +++++++++
Регистрация: 16.01.2004
Записей в блоге: 5
Я думаю, задача состоит в том, чтобы узнать, имеет ли пересечение языки порождаемые двумя регулярными выражениями. Попробовал погуглиь, но ничего не нашел.

Друг другом маск проверять по лайку не стоит так как для пары ?BС like A?С оно даст неверный результат, хотя обе маски подходят по ABC
Старый 15.01.2008, 17:13   #15  
Starling is offline
Starling
Участник
Дети Юза
 
530 / 76 (4) ++++
Регистрация: 20.10.2005
Адрес: Kiev
Цитата:
Сообщение от belugin Посмотреть сообщение
Друг другом маск проверять по лайку не стоит так как для пары ?BС like A?С оно даст неверный результат, хотя обе маски подходят по ABC
Я ожидал ture, но на практики получил false.
Вот такой if тоже false вернет
X++:
if("7*" like "76")
а вот такой true
X++:
if("76" like "7*")
Старый 15.01.2008, 17:18   #16  
belugin is offline
belugin
Участник
Аватар для belugin
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,622 / 2925 (107) +++++++++
Регистрация: 16.01.2004
Записей в блоге: 5
в-общем, ороший предлог окунуться в теорию формальных грамматик
Старый 15.01.2008, 17:24   #17  
AndyD is offline
AndyD
Участник
КОРУС Консалтинг
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
 
2,560 / 2479 (88) +++++++++
Регистрация: 20.08.2005
Без table1 вы не можете точно сказать - пересекаются значения, соответствующие маскам или нет. Потенциально, 7* и *7 могут вернуть одинаковые записи, но в вашем примере пересений нет.

По поводу like - левая часть проверяется как есть, без преобразования метасимволов
__________________
Axapta v.3.0 sp5 kr2
Старый 15.01.2008, 17:33   #18  
Starling is offline
Starling
Участник
Дети Юза
 
530 / 76 (4) ++++
Регистрация: 20.10.2005
Адрес: Kiev
Меня, пожалуй, устроит решение запросом с использованием table1, так как перспектива
Цитата:
Сообщение от belugin
в-общем, ороший предлог окунуться в теорию формальных грамматик
в восторг меня не приводит

Цитата:
Сообщение от AndyD Посмотреть сообщение
Без table1 вы не можете точно сказать - пересекаются значения, соответствующие маскам или нет. Потенциально, 7* и *7 могут вернуть одинаковые записи, но в вашем примере пересений нет.

По поводу like - левая часть проверяется как есть, без преобразования метасимволов
В примере пересечений нет, но если потенциально они возможны, то в идеале хотелось бы выдавать ошибку и не выполнять обновления table1
Старый 15.01.2008, 20:58   #19  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1152 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Записей в блоге: 19
Зацепило. Поигрался на тему. Сваял джоб-имитатор ситуации, использовав три временных буфера от таблицы InventTable. Получил набор хороших id-шников, которые можно засунуть, например, в map и далее уже без анализа использовать в цикле. Одним словом - выкладываю, а там, может, на что-то натолкнет еще...

P.S. 09:50 16.01.08. Добавил еще один временный буфер и сделал имитацию обновления исходной таблицы. Джоб обновил.
X++:
static void Test_6_star_7(Args _args)
{
    InventTable table1_t;       // исходная таблица
    InventTable tmpTable1_m;    // маски
    InventTable tmpTable2_g;    // хорошие id
    InventTable tmpTable3_u;    // обновления для хороших id
    // InventTable inventTable;
    ;

    // ниже везде id храним в ItemId, Amount в Height 
    //(просто так выбрали подходящие поля из InventTable)

    // имитация table1 (исходная таблица)
    table1_t.setTmp();
    ttsbegin;
    table1_t.ItemId = '7489'; table1_t.Height = 10; table1_t.doInsert();
    table1_t.ItemId = '7569'; table1_t.Height = 11; table1_t.doInsert();
    table1_t.ItemId = '6758'; table1_t.Height = 12; table1_t.doInsert();
    table1_t.ItemId = '6547'; table1_t.Height = 13; table1_t.doInsert();
    ttscommit;
/*
    // а можно прочитать из реальной постоянной таблицы
    // например, из inventTable
    ttsbegin;
    while select inventTable
    {
        table1_t.data(inventTable);
        table1_t.doInsert();
    }
    ttscommit;
*/
    info('--- 1. ДО ОБНОВЛЕНИЯ:');
    while select table1_t
        info( strFmt('id: %1, Amount: %2', table1_t.ItemId, table1_t.Height) );

    // имитация tmpTable1 (маски)
    tmpTable1_m.setTmp();
    ttsbegin;
    tmpTable1_m.ItemId = '*7'; tmpTable1_m.Height = 2; tmpTable1_m.doInsert();
    tmpTable1_m.ItemId = '6*'; tmpTable1_m.Height = 3; tmpTable1_m.doInsert();
    ttscommit;

    // хорошие id - во временной служебной таблице
    tmpTable2_g.setTmp();
    ttsbegin;

    while select ItemId, count(RecId)
        from table1_t group by ItemId
        join tmpTable1_m
            where table1_t.ItemId like tmpTable1_m.ItemId
    {
        if (table1_t.RecId==1)
        {
            tmpTable2_g.ItemId = table1_t.ItemId;
            tmpTable2_g.doInsert();
        }
    }
    ttscommit;

    // готовим набор обновлений (id и Amount) - во временной служебной таблице
    tmpTable3_u.setTmp();
    ttsbegin;

    while
        select ItemId from tmpTable2_g
          join Height from tmpTable1_m
            where tmpTable2_g.ItemId like tmpTable1_m.ItemId
    {
        tmpTable3_u.ItemId = tmpTable2_g.ItemId;
        tmpTable3_u.Height = tmpTable1_m.Height;
        tmpTable3_u.doInsert();
    }
    ttscommit;

    info('--- 2. ОБНОВЛЕНИЯ:');
    while select tmpTable3_u
        info( strFmt('id: %1, addAmount: %2', tmpTable3_u.ItemId, tmpTable3_u.Height) );

    // обновляем исходную таблицу
    ttsbegin;

    while 
        select forupdate table1_t join tmpTable3_u
            where table1_t.ItemId == tmpTable3_u.ItemId
    {
        table1_t.Height += tmpTable3_u.Height;
        table1_t.doUpdate();
    }
    ttscommit;

    info('--- 3. ПОСЛЕ ОБНОВЛЕНИЯ:');
    while select table1_t
        info( strFmt('id: %1, Amount: %2', table1_t.ItemId, table1_t.Height) );
}
В окне infolog:
Код:
--- 1. ДО ОБНОВЛЕНИЯ:
id: 6547, Amount: 13.00
id: 6758, Amount: 12.00
id: 7489, Amount: 10.00
id: 7569, Amount: 11.00
--- 2. ОБНОВЛЕНИЯ:
id: 6758, addAmount: 3.00
--- 3. ПОСЛЕ ОБНОВЛЕНИЯ:
id: 6547, Amount: 13.00
id: 6758, Amount: 15.00
id: 7489, Amount: 10.00
id: 7569, Amount: 11.00
Теги
join, like, фильтр, ax3.0

 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
Fred Shen: 'Not Like' in Dynamics AX Blog bot DAX Blogs 0 28.10.2006 16:40
Использование "like" при работе с классом "QueryBuildRange" poul DAX: Программирование 18 11.08.2006 12:20
как правильно использовать not like polygris DAX: Программирование 1 06.05.2006 16:59
Как правильно сделать проверку условия? Hidden DAX: Программирование 2 11.01.2006 13:05
Возможность использования Like в QueryBuildRange Koriolis DAX: Программирование 5 14.02.2005 17:43
Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

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

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

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