12.08.2010, 17:52 | #1 |
Участник
|
select в X++ и список значений в условии where
Здравия всем.
Хочу выбрать записи в X++ из таблицы СustInvoiceTrans с условием InventLocationId, заданном в виде строки 'СКЛАД1,СКЛАД2,СКЛАДN' Список InventLocationId формируется из параметров запроса -- сделано для того, чтобы пользователь не выбирал InventDimId. Код приведен ниже, но оператора IN, аналогичного T-SQL я не нашёл. Что нужно написать в условии where? X++: // ... получено из параметров запроса: str inventLocationId = 'СКЛАД1,СКЛАД2,СКЛАДN' select custInvoiceTrans join InventDim where inventDim.inventDimId == CustInvoiceTrans.InventDimId join inventLocation where inventLocation.InventLocationId == inventDim.InventLocationId && inventLocation.InventLocationId == ....... |
|
12.08.2010, 17:58 | #2 |
Участник
|
Используй queryBuildRange.value(....)
__________________
В подводной охоте главное вдох ... |
|
12.08.2010, 18:00 | #3 |
Axapta
|
Возможно, конечно. Использовать query.
|
|
12.08.2010, 18:00 | #4 |
Участник
|
|
|
12.08.2010, 18:04 | #5 |
Ищущий знания...
|
Цитата:
queryBuildRange.value(inventLocationId) и все
__________________
"Страх перед возможностью ошибки не должен отвращать нас от поисков истины." (с) С Уважением, Елизаров Артем |
|
12.08.2010, 18:05 | #6 |
Ищущий знания...
|
подробнее
X++: qbdsCustInvoceTrans = query.addDataSource(tablenum(CustInvoiceTrans)); qbdsInventDim = qbdsCustInvoceTrans .addDataSource(tablenum(InventDim)); qbdsInventDim .relation(true); qbdsInventDim.addRange(fieldNum(InventDim, InventLocationId)).value(inventLocationId);
__________________
"Страх перед возможностью ошибки не должен отвращать нас от поисков истины." (с) С Уважением, Елизаров Артем |
|
|
За это сообщение автора поблагодарили: Prophetic (1). |
13.08.2010, 09:23 | #7 |
Участник
|
Цитата:
Да, это решит проблему, благодарю. Однако, вопрос в том, что я пытаюсь модифицировать класс CustTransStatistics, в котором уже всё завязано на простую таблицу. Просто очень не хочется ВСЁ переписывать. Может быть есть ещё другой способ отфильтровать по складам? |
|
13.08.2010, 09:39 | #8 |
Moderator
|
У меня вот здесь Можно ли в SELECT использовать критерия вида "10..20" было некоторое подобие IN для таких случаев недлинных списков. Во всяком случае, визуально в составе select'а выглядит вполне удовлетворительно. Может, подойдёт приемчик?
|
|
|
За это сообщение автора поблагодарили: mazzy (2), lev (2), S.Kuskov (3), Prophetic (1). |
13.08.2010, 10:36 | #9 |
Участник
|
Как вариант используйте прямой запрос к базе с IN-ми и LIKE-ми )
__________________
В подводной охоте главное вдох ... |
|
|
За это сообщение автора поблагодарили: S.Kuskov (-1), Prophetic (1). |
13.08.2010, 10:42 | #10 |
Участник
|
Цитата:
Сообщение от Gustav
У меня вот здесь Можно ли в SELECT использовать критерия вида "10..20" было некоторое подобие IN для таких случаев недлинных списков. Во всяком случае, визуально в составе select'а выглядит вполне удовлетворительно. Может, подойдёт приемчик?
Последний раз редактировалось Prophetic; 13.08.2010 в 10:45. |
|
13.08.2010, 11:04 | #11 |
Участник
|
Нет. Не нужно так поступать.
Просто используйте вместо типа str, какой-нибудь расширенный тип данных, ни или на крайний случай пишите "str 30", т.е еграничте длину типа |
|
13.08.2010, 11:16 | #12 |
Участник
|
Цитата:
X++: inventLocationRange = str2con_RU(inventLocationId, ','); while select custInvoiceTrans where custInvoiceTrans.InvoiceDate == 01\04\2010 join InventDim where inventDim.inventDimId == CustInvoiceTrans.InventDimId && #sqlIn(inventDim.InventLocationId,inventLocationRange) |
|
13.08.2010, 11:48 | #13 |
Moderator
|
"А, пожалуйста!" (с) "О чём говорят мужчины"
А если не создавать отдельную переменную-контейнер и вставить вызов str2con_RU прямо в параметр макроса? У меня на 3.0 SP4 прокатило: X++: static void test_SQL_Imitation_2(Args _args) { #macrolib.SQL_Imitation Dialog dialog; DialogField dialogField; InventLocation inventLocation; ; dialog = new Dialog('Тест имитации SQL IN'); dialogField = dialog.addFieldValue(Types::String, 'СКЛАД1,СКЛАД2,СКЛАДN', 'Введите значения через запятую (не более 10)'); if (dialog.run()) { while select inventLocation where #sqlIn( inventLocation.InventLocationId, str2con_RU(dialogField.value(),',') ) { info (inventLocation.InventLocationId); } } } |
|
13.08.2010, 11:50 | #14 |
Moderator
|
Цитата:
Сообщение от Gustav
У меня вот здесь Можно ли в SELECT использовать критерия вида "10..20" было некоторое подобие IN для таких случаев недлинных списков. Во всяком случае, визуально в составе select'а выглядит вполне удовлетворительно. Может, подойдёт приемчик?
__________________
Андрей. |
|
13.08.2010, 11:59 | #15 |
Участник
|
Цитата:
Сообщение от Gustav
"А, пожалуйста!" (с) "О чём говорят мужчины"
А если не создавать отдельную переменную-контейнер и вставить вызов str2con_RU прямо в параметр макроса? У меня на 3.0 SP4 прокатило: X++: static void test_SQL_Imitation_2(Args _args) { #macrolib.SQL_Imitation Dialog dialog; DialogField dialogField; InventLocation inventLocation; ; dialog = new Dialog('Тест имитации SQL IN'); dialogField = dialog.addFieldValue(Types::String, 'СКЛАД1,СКЛАД2,СКЛАДN', 'Введите значения через запятую (не более 10)'); if (dialog.run()) { while select inventLocation where #sqlIn( inventLocation.InventLocationId, str2con_RU(dialogField.value(),',') ) { info (inventLocation.InventLocationId); } } } Хотя неясно, почему компилятор не проверил тип возвращаемого значения. |
|
13.08.2010, 11:59 | #16 |
Участник
|
Позволю себе немного модифицировать макрос SqlIn. Идея таже, но реализация не через контейнер, а через масив. Плюс ещё добавлена проверка выхода за границы масива.
X++: static void Job_SQL_IN(Args _args) { #LOCALMACRO.sqlIn ( ((%3 <= 1) && (%1 == %2[1])) || ((%3 <= 2) && (%1 == %2[2])) || ((%3 <= 3) && (%1 == %2[3])) || ((%3 <= 4) && (%1 == %2[4])) || ((%3 <= 5) && (%1 == %2[5])) || ((%3 <= 6) && (%1 == %2[6])) || ((%3 <= 7) && (%1 == %2[7])) || ((%3 <= 8) && (%1 == %2[8])) || ((%3 <= 9) && (%1 == %2[9])) || ((%3 <= 10) && (%1 == %2[10])) ) #ENDMACRO custInvoiceTrans custInvoiceTrans; InventDim InventDim; inventLocationId inventLocationId; container inventLocationCon; int n; inventLocationId inventLocationArr[10]; ; // inventLocationId = ...; inventLocationCon = str2con_RU(inventLocationId, ','); for (n = 1; n <= conlen(inventLocationCon); n++) { inventLocationArr[n] = conpeek(inventLocationCon, n); } n--; while select custInvoiceTrans where custInvoiceTrans.InvoiceDate == 01\04\2010 join InventDim where inventDim.inventDimId == CustInvoiceTrans.InventDimId && #sqlIn(inventDim.InventLocationId, inventLocationArr, n) { //... } } |
|
|
За это сообщение автора поблагодарили: lev (1). |
13.08.2010, 12:18 | #17 |
Moderator
|
В общем, компилятор обижается, когда параметром макроса выступает переменная конкретного "плохого" типа (контейнер или безразмерная строка). Если же переменную заменить на вызов функции, пусть даже и возвращающей "плохой" тип, то всё получается:
X++: static void test_SQL_Imitation_3(Args _args) { #macrolib.SQL_Imitation InventLocation inventLocation; container c = ['СКЛАД1','СКЛАД2','СКЛАДN']; // не работает container c() // работает { return ['СКЛАД1','СКЛАД2','СКЛАДN']; } ; while select inventLocation //where #sqlIn( inventLocation.InventLocationId, c ) // не работает where #sqlIn( inventLocation.InventLocationId, c() ) // работает { info (inventLocation.InventLocationId); } } |
|
13.08.2010, 12:28 | #18 |
Участник
|
Тоже неплохо, благодарю. Согласен, что извращения, но все же иногда надо.
|
|
13.08.2010, 14:02 | #19 |
Участник
|
Цитата:
Ну, разбиваешь строку на элементы в тот же массив, потом цикл по массиву и вызов метода, куда в качестве параметра передаешь значение очередного элемента массива. Не надо никаких переделок на Query и "танцев с бубном" в виде макросов. Все просто и понятно. Насчет скорости... Ну, это надо посмотреть. Тут все зависит от того, сколько значений будет в передаваемой строке |
|
13.08.2010, 17:02 | #20 |
Участник
|
Цитата:
Сообщение от Владимир Максимов
А почему не сделать напрашивающееся решение в виде цикла в котором по очереди передаешь ОДНО значение?
Ну, разбиваешь строку на элементы в тот же массив, потом цикл по массиву и вызов метода, куда в качестве параметра передаешь значение очередного элемента массива. Не надо никаких переделок на Query и "танцев с бубном" в виде макросов. Все просто и понятно. Насчет скорости... Ну, это надо посмотреть. Тут все зависит от того, сколько значений будет в передаваемой строке |
|
Теги |
select, where |
|
Похожие темы | ||||
Тема | Ответов | |||
QueryBuildRange в select.. where | 11 | |||
Разница NotInTTS и Found | 6 | |||
Ошибка при старте АОСа | 4 | |||
Вопрос про Demand Planner | 4 | |||
select * where ... | 10 |
|