|
v7: помогите запрос по 1с++ | ☑ | ||
---|---|---|---|---|
0
Loko
24.09.14
✎
04:41
|
всем привет!
есть внешняя БД. подключаюсь к ней из 1с7. нужно выбрать список товаров, с определенным списком кодов (кодов бывает от 1000 до 2000 примерно). пробую через уложить список, предварительно добавив в список значений все коды - выходит пустая таблица. |SELECT * |FROM PriceList |WHERE |KodTovar IN (SELECT Val FROM #Коды)"; пробовал в строку перечислить все коды (KodTovar IN #Коды) но там строка огромного размера - не получается. в 8-ке просто через массив делается. а как быть в 7-ке? |
|||
1
МастерВопросов
24.09.14
✎
05:03
|
(0) если стоит 1cPP.dll, то УложитьСписок, там же в мануале всё написано
|
|||
2
Loko
24.09.14
✎
05:08
|
да, я так и пробовал (написал же). не получается.
|
|||
3
МастерВопросов
24.09.14
✎
05:09
|
Отбор по списку или группе
Для таких случаев у объекта ODBCRecordset есть метод УложитьСписокОбъектов(Список, Таблица, ВидСправочника) и УложитьСписокОбъектов13(Список, Таблица) Список – это список или группа. После выполнения этого метода появляется таблица с именем Таблица и колонками Val, IsFolder Однако не стоит злоупотреблять этим методом. Анализируя производительность можно увидеть, что этот метод на группах работает медленно и это совершенно очевидно, т.к. группа может содержать огромное число элементов, которые надо переписать во временную таблицу. ГОРАЗДО эффективней получить список подгрупп входящих в выбранную группу и делать условие по принадлежности к родителю, а не по ID Пример: Выберем все документы реализации, у которых склад входит в выбранную группу ТекстЗапроса = " |SELECT | Док.IDDoc as [Док $Документ.Реализация] |FROM | $Документ.Реализация as Док |WHERE | $Док.Склад IN (SELECT Val FROM #Группа)"; RS.УложитьСписокОбъектов(ВыбГруппа, "#Группа", "Склады"); Замечание: Рекомендуется использовать локальные временные таблицы – префикс #. В этом случае не нужно заботиться об уникальности имени таблицы для разных пользователей, а также об их последующем удалении. В ДБФ версии драйвер сам создает такие таблицы и сам же генерирует им имя. Можно сделать универсальный способ получения имени таблицы, работающий как в ДБФ, так и в СКЛ: ИмяТаблицы="#Группа "; Запрос.УложитьСписокОбъектов(СписокРодителей,ИмяТаблицы); ТекстЗапроса=" (SELECT Val FROM "+ИмяТаблицы+")"; В случае СКЛ запрос выполнится из таблицы "#Группа", а в случае ДБФ система сгенерит имя и вернет ее в переменную ИмяТаблицы. В случае ДБФ имя временной таблицы выглядит так ‘f6d3b234a56c765f52da’ что, конечно не очень красиво для текста запроса(особенно если его еще и разбирать на ошибки нужно или на дополнения). Можно сделать запрос более красивым и универсальным: для этого воспользуемся методом УстановитьТекстовыйПараметр() ИмяТаблицы="#Группа"; Запрос.УложитьСписокОбъектов(СписокРодителей,ИмяТаблицы); Запрос. УстановитьТекстовыйПараметр ("Группа", ИмяТаблицы); ТекстЗапроса=" (SELECT Val FROM "+?(ЭтоСКЛ=0,":","#")+"Группа)"; В этом случае если работа происходит в СКЛе то запрос проигнорирует текстовый параметр, а если в ДБФ, то вместо :Группа подставит имя временной таблицы. Тот же пример, но по списку контрагентов: ТекстЗапроса = " |SELECT | Док.IDDoc as [Док $Документ.Реализация] |FROM | $Документ.Реализация as Док |WHERE | $Док.Контрагент IN (SELECT Val FROM #Группа)"; RS.УложитьСписокОбъектов13(Список, "#Группа"); Обычно при написании отчетов нужно делать переменные условия: по всем, по элементы, по группе или по списку. Отрабатывать все варианты в каждом отчете – проще застрелиться. И для того, чтобы так не делать мною был разработан класс обертка ЗапросSQL (можно найти на acsent.nm.ru). Суть это класса состоит в макроподстановках Пример: Запрос = СоздатьОбъект("ЗапросSQL"); Запрос.ДобавитьУсловие("$Док", "Склад", "", ВыбСклад, ""); Запрос.Текст = " |SELECT | Док.IDDoc as [Док $Документ.Реализация] |FROM | $Документ.Реализация as Док |WHERE | %Склад "; ТЗ = Запрос.Выполнить(); ТЗ.ВыбратьСтроку(); В зависимости от значения ВыбСклад в запрос встанет условие: 0 = 0 (Пустое значение, по всем) $Док.Склад = :Склад (Выбран элемент) $Док.Склад IN (SELECT Val FROM #__Склад) (Выбрана группа или список) На небольших списках лучше обойтись без метода «уложения». Я использую следующую конструкцию |SELECT | Док.IDDoc as Док |FROM | $Документ.Реализация as Док |WHERE | $Док.Склад IN (' 6', ' 3', ' 2') | "; Где ' 6' – внутренний идентификатор элемента справочника «склады». Получить его можно с помощью метода ЗначениеВСтрокуБД() объекта «MetaDataWork» МД=СоздатьОбъект("MetaDataWork"); Условия ="("; Для Н=1 По Список.РазмерСписка() Цикл Условия = Условия + "'" + МД.ЗначениеВСтрокуБД(Список.ПолучитьЗначение(Н)) + ?( Н=Список.РазмерСписка(),")","',"); КонецЦикла; Этот способ удобен тем, что нет лишней траты времени на выгрузку списка значений во временную таблицу. |
|||
4
МастерВопросов
24.09.14
✎
05:10
|
(2) в семерке вместо одномерного массива используется "СписокЗначений"
|
|||
5
МастерВопросов
24.09.14
✎
05:12
|
||||
6
Loko
24.09.14
✎
05:12
|
(4) да это понятно. я так и сделал: глРС.УложитьСписокОбъектов13(КодыТовара, "#Коды");
где кодыТовара - СписокЗначений. в (0) посте после запроса я другой способ пробую уже. |
|||
7
МастерВопросов
24.09.14
✎
05:14
|
(6) закеж код, где ты СписокЗначений заполняешь.
|
|||
8
МастерВопросов
24.09.14
✎
05:16
|
"KodTovar IN (SELECT Val FROM #Коды)"
KodTovar - это ссылка, или код товара в КодыТовара у тебя ссылки, или кода? |
|||
9
Loko
24.09.14
✎
05:16
|
(7)
ВыбратьСтроки(); Пока ПолучитьСтроку()=1 Цикл СпрИзг.ИспользоватьВладельца(Товар); СпрИзг.ВыбратьЭлементы(); Пока СпрИзг.ПолучитьЭлемент() = 1 Цикл Если ПустоеЗначение(СпрИзг.КодФК)=0 Тогда КодыТовара.ДобавитьЗначение(СокрЛП(СпрИзг.КодФК)); КонецЕсли; КонецЦикла; КонецЦикла; |
|||
10
Loko
24.09.14
✎
05:17
|
(8) коды. текст.
|
|||
11
МастерВопросов
24.09.14
✎
05:21
|
(10) попробуй тогда такое условие
RTRIM(LTRIM(KodTovar)) IN (SELECT Val FROM #Коды) |
|||
12
Loko
24.09.14
✎
05:24
|
(11) не взлетает.
|
|||
13
МастерВопросов
24.09.14
✎
05:27
|
(12) что не взлетает? Ошибка, или пустой запрос.
Ты бы уже заказал свой реальный запрос, а не огрызок в (0) |
|||
14
Loko
24.09.14
✎
05:28
|
один ньюанс: во внешней БД коды эти в формате число, в 1С-ке как строка. переделал на КодыТовара.ДобавитьЗначение(Число(СокрЛП(СпрИзг.КодФК)));
но не идет... |
|||
15
Loko
24.09.14
✎
05:28
|
(13) пустая таблица результат
|
|||
16
ahachack2
24.09.14
✎
05:30
|
на форуме 1cpp вроде писали что для примитивных типов типа строка метод УложитьСписокОбъектов не работает.
Я для базы в формате sql обходил так: делал свою временную таблицу из одной колонки - и заполнял самостоятельно значениями, в основном запросе - обращался к созданной таблице |
|||
17
Loko
24.09.14
✎
05:33
|
(16) а можно код как заполняли таблицу?
|
|||
18
ahachack2
24.09.14
✎
05:35
|
RS=СоздатьОбъект("ODBCRecordset");
RS.Выполнить("drop table #TEMP_INDEX_SVODNIY"); RS.Выполнить("create table #TEMP_INDEX_SVODNIY(S char(11),primary key clustered (S))"); Для сч=1 по СписокИндексов.РазмерСписка() Цикл RS.Выполнить("insert into #TEMP_INDEX_SVODNIY(S) values('"+СписокИндексов.ПолучитьЗначение(сч)+"')"); КонецЦикла; |
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |