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

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 08.09.2005, 12:04   #1  
6apcyk is offline
6apcyk
Участник
 
57 / 11 (1) +
Регистрация: 17.08.2005
Помогите с query
Есть таблица1, таблица2, таблица3. У которых есть общее поле itemId(у таблиц таблица2 и таблица3 может дублироваться).

Надо получить query такое что в нем будут только те записи, для которых itemId есть в третей или во второй таблице.
Старый 08.09.2005, 12:51   #2  
Bega is offline
Bega
Участник
Аватар для Bega
 
382 / 444 (15) +++++++
Регистрация: 18.08.2005
Адрес: Москва
что вроде этого пойдет ?:
Query q;
QueryBuildDataSource qbr, qbr2, qbr3;
;
qbr = q.addDataSource(tablenum(Table1));
qbr2 = qbr.addDataSource(tablenum(Table2));
qbr2.addLink(tablenum(Table1, ItemId), tablenum(Table2, ItemId));
qbr2.joinMode(JOINMODE::ExistsJoin);
qbr3 = qbr.addDataSource(tablenum(Table3));
qbr3.addLink(tablenum(Table1, ItemId), tablenum(Table3, ItemId));
qbr3.joinMode(JOINMODE::ExistsJoin);
Старый 08.09.2005, 12:58   #3  
6apcyk is offline
6apcyk
Участник
 
57 / 11 (1) +
Регистрация: 17.08.2005
так я тоже пробовал
Этот запрос join-ит по пересечению таблиц 2 и 3
так что не подходит
Старый 08.09.2005, 13:00   #4  
AndyD is offline
AndyD
Участник
КОРУС Консалтинг
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
 
2,560 / 2479 (88) +++++++++
Регистрация: 20.08.2005
2 Bega

Неа. Не правильно. На сервер пойдут отдельные запросы для каждой таблицы

2 барсук

PHP код:
Query Q = new Query();
;
    
Q.addDataSource(tablenum(Table1));
    
Q.dataSourceTable(tablenum(Table1)).addDataSource(tablenum(Table2));
    
Q.dataSourceTable(tablenum(Table2)).joinMode(JoinMode::ExistsJoin);
    
Q.dataSourceTable(tablenum(Table2)).addLink(fieldnum(table1ItemId), fieldnum(table2ItemId));

    
Q.dataSourceTable(tablenum(Table2)).addDataSource(tablenum(Table3));
    
Q.dataSourceTable(tablenum(Table3)).joinMode(JoinMode::InnerJoin);
    
Q.dataSourceTable(tablenum(Table3)).addLink(fieldnum(table2ItemId), fieldnum(table3ItemId)); 
PS. Хотя и без ExistsJoin можно все и на InnerJoin сделать
__________________
Axapta v.3.0 sp5 kr2
Старый 08.09.2005, 13:32   #5  
6apcyk is offline
6apcyk
Участник
 
57 / 11 (1) +
Регистрация: 17.08.2005
2 AndyD
вопрос как в этот запрос оставляет в таблице 1, те записи из таблицы 3 которых нет в таблице 2?
Старый 08.09.2005, 13:45   #6  
ahtoh
Гость
 
n/a
Цитата:
Изначально опубликовано 6apcyk
2 AndyD
вопрос как в этот запрос оставляет в таблице 1, те записи из таблицы 3 которых нет в таблице 2?
никак, потому что он неправильный
Старый 08.09.2005, 13:46   #7  
ahtoh
Гость
 
n/a
можете добавить в базу знаний: 2 экзист джойна эквивалентны экзист + иннер джойну
Старый 08.09.2005, 14:05   #8  
Bega is offline
Bega
Участник
Аватар для Bega
 
382 / 444 (15) +++++++
Регистрация: 18.08.2005
Адрес: Москва
На чистом SQL это выглядело бы так:

select Table1.*
from Table1
left join Table2 on Table2.ItemId = Table1.ItemId
left join Table3 on Table3.ItemId = Table1.ItemId
where not Table2.ItemId is null or not Table3.ItemId is null
--либо
select Table1.*
from Table1
where
exists(select * from Table2 where Table2.ItemId = Table1.ItemId)
or
exists(select * from Table3 where Table3.ItemId = Table1.ItemId)

В одном Query такое наверное не сделаешь.
Старый 08.09.2005, 14:11   #9  
ahtoh
Гость
 
n/a
единственное решение, которое приходит на ум - создать вьюшку из table2 и table3 и полями соотв itemid2, itemid3 и в запросе писать table1.itemid == view.itemid2 || table1.itemid == view.itemid3
Старый 08.09.2005, 14:17   #10  
AndyD is offline
AndyD
Участник
КОРУС Консалтинг
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
 
2,560 / 2479 (88) +++++++++
Регистрация: 20.08.2005
Извиняюсь, неправильно прочитал условия.

Я предлагал для выбора по "И"
__________________
Axapta v.3.0 sp5 kr2
Старый 08.09.2005, 14:47   #11  
Владимир Максимов is offline
Владимир Максимов
Участник
КОРУС Консалтинг
 
1,691 / 1195 (43) ++++++++
Регистрация: 13.01.2004
Записей в блоге: 3
Мне кажется, что сделать это через Query - не получится.

Дело в том, что Query собирает все условия через AND. Вписать OR получается далеко не всегда. Обычно для этого приходится сильно "извращаться".

Стандартное решение - это делать Query по первой таблице, а внутри перебора полученных записей (while (QueryRun.next())) проверять факт вхождения во вторую или третью.

"НЕ стандартное" - это формировать запрос напрямую на сервере через объект Connection.
Старый 08.09.2005, 15:04   #12  
AndyD is offline
AndyD
Участник
КОРУС Консалтинг
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
 
2,560 / 2479 (88) +++++++++
Регистрация: 20.08.2005
Если вопрос в том, чтобы пробежать по Query и получить значения, то это можно реализовать. Но мне кажется, что данном случае речь идет о визуализации. 2 6apcyk?
__________________
Axapta v.3.0 sp5 kr2
Старый 08.09.2005, 16:07   #13  
ahtoh
Гость
 
n/a
Цитата:
Изначально опубликовано Владимир Максимов
Мне кажется, что сделать это через Query - не получится.
я выше написал, как это можно сделать
Старый 08.09.2005, 16:16   #14  
Владимир Максимов is offline
Владимир Максимов
Участник
КОРУС Консалтинг
 
1,691 / 1195 (43) ++++++++
Регистрация: 13.01.2004
Записей в блоге: 3
Цитата:
Изначально опубликовано ahtoh
я выше написал, как это можно сделать
Так ведь не через Query! Точнее, не чистый Query.

Причем не совсем ясно, как предполагается делать вьюшку. Ведь в этом случае нужно объединение по FULL JOIN. Иначе условие OR не получиться. Я не в курсе, можно такое во вьюшке сделать?
Старый 08.09.2005, 16:43   #15  
ahtoh
Гость
 
n/a
что значит не query
а full join сделать проще некуда - relations не указываешь да и все

попробуй на досуге выполнить select ledgertrans join ledgertrans2 поймешь, что джойн тут cамый, что ни на есть ФУЛЛ
Старый 08.09.2005, 17:10   #16  
AndyD is offline
AndyD
Участник
КОРУС Консалтинг
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
 
2,560 / 2479 (88) +++++++++
Регистрация: 20.08.2005
Получите декартово произведение, т.е. каждая запись из таблицы1 будет объединяться с каждой записью из таблицы2. В результате кол-во записей во view будет count(таблица1) * count(таблица2)
__________________
Axapta v.3.0 sp5 kr2
Старый 08.09.2005, 17:20   #17  
Владимир Максимов is offline
Владимир Максимов
Участник
КОРУС Консалтинг
 
1,691 / 1195 (43) ++++++++
Регистрация: 13.01.2004
Записей в блоге: 3
Цитата:
Изначально опубликовано AndyD
Получите декартово произведение, т.е. каждая запись из таблицы1 будет объединяться с каждой записью из таблицы2. В результате кол-во записей во view будет count(таблица1) * count(таблица2)
В данном случае - это не принципиально.

Основная цель - это получить во View полный набор значений ItemId, как из второй, так и из первой таблицы (объединение значений). Это можно сделать через UNION, FULL JOIN или через декартово произведение. Суть не измениться. Хотя, конечно, при декартовом произведении записей будет больше всего.

Дальше уже надо смотреть, что получиться быстрее - такая вьюха или перебор в цикле.
Старый 08.09.2005, 17:46   #18  
AndyD is offline
AndyD
Участник
КОРУС Консалтинг
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
 
2,560 / 2479 (88) +++++++++
Регистрация: 20.08.2005
Зачем перебор в цикле?

PHP код:
table1      tbl;
query       q = new Query();
QueryRun    qr;
;

Q.addDataSource(tablenum(Table1));
Q.dataSourceTable(tablenum(Table1)).addDataSource(tablenum(Table2));
Q.dataSourceTable(tablenum(Table2)).joinMode(JoinMode::InnerJoin);
Q.dataSourceTable(tablenum(Table2)).addLink(fieldnum(table1ItemId), fieldnum(table2ItemId));

Q.addDataSource(tablenum(Table1));

Q.dataSourceTable(tablenum(Table1), 2).addDataSource(tablenum(Table3));
Q.dataSourceTable(tablenum(Table3)).joinMode(JoinMode::InnerJoin);
Q.dataSourceTable(tablenum(Table3)).addLink(fieldnum(table1ItemId), fieldnum(table3ItemId));

Q.dataSourceTable(tablenum(Table3)).addDataSource(tablenum(Table2));
Q.dataSourceTable(tablenum(Table2), 2).joinMode(JoinMode::NoExistsJoin);
Q.dataSourceTable(tablenum(Table2), 2).addLink(fieldnum(table3ItemId), fieldnum(table2ItemId));

qr = new QueryRun(q);
while (
qr.next())
{
    
tbl qr.getNo(1);
    if (!
tbltbl qr.getNo(3);
    
info(tbl.ItemId);

В принципе можно разбить на два отдельных запроса. Минусы - записи отсортированы сначала по table2.itemId, а затем по table3.itemId. И для просмотра неудобно.

По повод view - каким образом объединять ее с table1? Ведь в результате получим соответствующие увеличение кол-ва записей для датасорса.

Единственное верное решение в данном случае - использование UNION. Как грязный xак - можно подправить view на сервере
__________________
Axapta v.3.0 sp5 kr2
Старый 08.09.2005, 18:07   #19  
Владимир Максимов is offline
Владимир Максимов
Участник
КОРУС Консалтинг
 
1,691 / 1195 (43) ++++++++
Регистрация: 13.01.2004
Записей в блоге: 3
Приведенный код не решает поставленную задачу. У тебя получилось примерно следующее:

( Table1.ItemId = Table2.ItemId )
Декартово произведение
(Table1.ItemId = Table3.ItemId AND Table3.ItemId NOT EXISTS(Table2.ItemId))

Вся проблема именно в том, что объединение пойдет не по типу UNION (что предполагается), а именно как декартово произведение. Представляешь количество "мусора"?

А то, что предлагает ahtoh это примерно следующее:

Table1.ItemId EXISTS((Table2.ItemId) декартово произведение (Table3.ItemId))

Поскольку составить такой Query не получится, то он предлагает то, что внутри Exists оформить как отдельный View.

Все корректно. Вопрос только в скорости такой выборки.
Старый 08.09.2005, 20:02   #20  
AndyD is offline
AndyD
Участник
КОРУС Консалтинг
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
 
2,560 / 2479 (88) +++++++++
Регистрация: 20.08.2005
Нет, там по другому. На сервер пойдет два запроса результаты которых будут объеденены на клиенте. Обратите внимание table1 там добавляется два раза. Т.е получится следующее

datasource1(table1) - datasource3(table1)
--------------------------------------
table1.itemid = table2.itemId - пусто
table1.itemid = table2.itemId - пусто
table1.itemid = table2.itemId - пусто
пусто - table1.itemid = table3.itemId
пусто - table1.itemid = table3.itemId
пусто - table1.itemid = table3.itemId

По поводу view я уже и сам понял, просто не учел про ExistsJoin
Тут есть замечание - необходимо не Table1.ItemId Exists(), а Table1.Itemid IN. Как его задать - не предствляю себе.

Если задавать ExistsJoin, то получается
PHP код:
    Q.addDataSource(tablenum(Table1), "t1");
    
Q.dataSourceTable(tablenum(Table1)).addDataSource(tablenum(View1), "v1");
    
Q.dataSourceTable(tablenum(View1)).joinMode(JoinMode::ExistsJoin);
    
Q.dataSourceTable(tablenum(View1)).addRange(fieldnum(view1itemid1)).value("((v1.itemId1 == t1.itemId) || (v1.itemId2 == t1.itemId))"); 
Но тут, как не раз было замечено, встает вопрос производительности
__________________
Axapta v.3.0 sp5 kr2
 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
Dynamics AX: QueryRun and Query Objects - Binding operation failed to allocate buffer space Blog bot DAX Blogs 0 03.04.2009 08:05
palleagermark: Sample union query from AX 2009 Blog bot DAX Blogs 0 11.07.2008 20:05
Dynamics AX Geek: Using query() Blog bot DAX Blogs 0 28.10.2006 16:40
Помогите новичку в создании Query lev DAX: Программирование 2 19.06.2006 10:29
Проблема с составлением Query axaLearner DAX: Программирование 10 01.12.2005 15:00

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

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

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