Простейший запрос через 1sqlite - передать параметр?

Автор MWW_Ruza, 22 июня 2025, 16:57

« назад - далее »

MWW_Ruza

Добрый день!
Мне стыдно, аж ж... красная, на дворе уже 2025 год, а я в трех соснах блуждаю...
В общем, как-то не приходилось мне такие запросы делать, с параметрами...
Все, что до этого делал с применением 1sqlite - это получить список элементов, получить список групп, найти по наименованию... Ну, и парсинг JSON... Как-то на раз прокатывало, никогда не возникало проблем.
А тут, захотел построить запрос для волучения списка номенклатуры по выбранной группе, и встрял...
Не могу понять, как правильно передать параметр?
Вроде как все элементарно, но, получаю ошибку:


    |SELECT
	|   Номенклатура.ID [Номенклатура $Справочник.Номенклатура]
    |FROM
	|    Справочник_Номенклатура AS Номенклатура 
	|WHERE  Номенклатура.ISFOLDER = 2 AND Номенклатура.PARENTID = :ИдГр
	|";
	Запрос.Отладка();

	Запрос.Подставлять("ИдГр", ВыбГруппа);
	
	Запрос.Подготовить(ТекстЗапроса);

	Тз = Запрос.ВыполнитьЗапрос(ТекстЗапроса);

ВыбГруппа - поле справочника Номенклатура на форме, куда выбрана группа.
Вроде как и подставляет ID группы в нужное место, но ругается, что "Ошибка подстановки текстового параметра ИдГр - Неизвестный параметр"...
Как неизвестный? Почему неизвестный? Он его преобразует из реквизита, получает ID этой группы, правильно, как в таблице 1С, на скриншоте с включенной отладкой видно...
Но, выдает ошибку и результат пустой...
Если в это условие без параметра строкой передаю:
|WHERE  Номенклатура.ISFOLDER = 2 AND Номенклатура.PARENTID = '     1   '
то запрос отрабатывает, возвращает правильно все элементы группы, порядка 1200 штук...
Передача ИД через параметр в готовом виде тоже не дает результата, все 1 в 1...
Помогите, всю голову сломал...
Чувствую, какая-то мелочь, что-то в синтаксисе не верно, но не могу въехать какая...
Во вложении обработка-пример, со всеми моими "мудовыми рыданиями", закомментированными.
Документацию читал, в интернете искал...
Вот, на Мисте, 9 лет назад было похожее:

Практически, тоже, что и у меня... Но, видимо, чего-я не вижу :(

Djelf


Вот это не надо делать: "Запрос.Подготовить(ТекстЗапроса);" если нет динамических парамеров через собаку.

MWW_Ruza

Ооооо!!!!
Антон, спасибо!
Так - работает :-)))
В таблице 1228 строк!
То, что нужно.

Тогда, можно еще вопросик, чуть сложнее...
Как вывести в запрос все элементы выбранной группы, в том числе и вложенных подгрупп всех уровней?
Тут, я так понимаю, нкжно уже другой какой-то оператор применять, не по ИД отбирать...

MWW_Ruza

Цитата: MWW_Ruza от 22 июня 2025, 17:47Тут, я так понимаю, нкжно уже другой какой-то оператор применять, не по ИД отбирать...
Нет, я конечно понимаю, что можно внутри запроса отдельным подзапросом получить список групп входящих в группу верхнего уровня, а потом получить список элементов, принадлежащих этим группам, но... Как-то это криво... Не верится, что это так и надо делать. Наверняка должно быть что-то типа "ВГруппе", или я ошибаюсь и такого нет?

Djelf

Я постил на форуме 1с++, но там найти что-то уже сложно.
Вот если бы кто-то его заморозил или сдампил, то можно было бы сконвертировать замороженный архив на SMS, и можеть бы АльФ его развернул, ну раз нет, так нет...

Djelf

Вот запрос всех товаров в группе
-- Запрос номенклатуры в группе
WITH CTE(ID,PARENTID,ISFOLDER) AS(
	SELECT T1.ID,T1.PARENTID,T1.ISFOLDER
	FROM Справочник_Номенклатура AS T1
	WHERE t1.ID = '    D3Б  '
	
	UNION ALL SELECT
		T2.ID,T2.PARENTID,T2.ISFOLDER
	FROM cte
	LEFT JOIN Справочник_Номенклатура AS T2 ON T2.PARENTID=CTE.ID
	WHERE CTE.ISFOLDER=1
LIMIT 5000
)
SELECT
	cte.ID [Номенклатура :Справочник.Номенклатура]
	,cte.PARENTID [Родитель :Справочник.Номенклатура]
	,cte.ID
	,cte.PARENTID
	,cte.ISFOLDER
FROM cte
WHERE cte.ISFOLDER=2

Djelf

Можно завернуть в неявное cte и в какую-то пользовательскую функцию генерации последовательности (sqlite это умеет), я в укладке объектов такое делал, но зачем? Всего-то 10 строк кода...

Djelf

Хинт для последних версий
- WITH CTE(ID,PARENTID,ISFOLDER) AS(
+ WITH CTE(ID,PARENTID,ISFOLDER) AS MATERIALIZED (
эта штука делает сте запрос перманентным, кеширует в памяти, кстати и вьюхи тоже (запросы к бд отсутстуют, ну разве что в первый раз)
что при повторном обращении к cte или вьюхе значительно увеличивает скорость
поначалу  MATERIALIZED было по-умолчанию, потом оказалось что иногда вызывает регресии, отменили, теперь надо указывавать принудительно

MWW_Ruza


Djelf

Играйся... новые версии: ничё интересного, будем подождать.

MWW_Ruza

Работает :)
Это закомментировал: LIMIT 5000
У меня, у одних клиентов очень по хитрож**ому справочник организован...
Там в Номенклатуре всего две папки верхнего уровня, а все остальное внутри:

Но, даже в таком варианте, очень быстро работает - меньше секунды.
Во вложении тестовая обработка с обеими вариантами, может кому пригодится.

Djelf

limit в сте, да и вообще всегда стоит ставить при отладке, а в cte это особенно важно, если чуток ошибся, то будет такая рекурсия, что 1с по памяти вылетит. забыл убрать в запросе.

з.ы. ты личное сообщение на этом форуме то смотришь? я тебе посылал интересное решение с разбором json, помнится ты этого когда-то хотел, но тогда решение не нашлось...

MWW_Ruza

Цитата: Djelf от 23 июня 2025, 13:52з.ы. ты личное сообщение на этом форуме то смотришь?

Не видел... Не сказал бы, так и не заметил бы.
Спасибо, буду разбираться.

Arbuz

Цитата: MWW_Ruza от 22 июня 2025, 17:47Тогда, можно еще вопросик, чуть сложнее...
Как вывести в запрос все элементы выбранной группы, в том числе и вложенных подгрупп всех уровней?
Тут, я так понимаю, нкжно уже другой какой-то оператор применять, не по ИД отбирать...

Дык, есть же УложитьОбъекты()

Цитата
1sqlite 
Объект SQLiteBase :: УложитьОбъекты / PutObjects

Синтаксис: УложитьОбъекты(Объект, ИмяТаблицы, [КакПостоянную], [Иерархия])

Параметры:
Объект - тип: СписокЗначений, Справочник, Счет. Выгружаемые объекты.
ИмяТаблицы - тип: Строка. Имя созываемой в базе данных таблицы.
КакПостоянную - тип: Число. 1 - создать обычную таблицу, 0 - создать временную таблицу. Необязательный параметр. По умолчанию 0.
Иерархия - тип: Строка. Название справочника или плана счетов для разворота групп справочника или групп счетов. Необязательный параметр. По умолчанию - пустая строка.
Возвращает: нет

Описание: Загружает значение либо список значений в базу данных, как таблицу базы данных.

В базе данных создается таблица с заданным именем с одним полем val. Если таблица с таким именем существует, она уничтожается. В данную таблицу выгружаются внутренние идентификаторы объектов в формате char(9). Если первым параметром передан список значений, в таблицу укладываются значения из переданного списка.

Если задана иерархия (название справочника либо плана счетов), то вместо объектов-групп выгружаются все входящие в группу элементы/счета всех нижележащих уровней. Сами группы при этом не выгружаются. Работа с иерархией выполняется только в дбф-базах, в sql-версии 1С будет генерироваться исключение.

Перед выполнением метода проверяется только то, что первый параметр либо список значений, либо справочник, либо счет. Проверка выгружаемых значений на то, что они действительно являются справочниками/счетами нужного вида - не производится, и вся ответственность за это возлагается на пользователя.

При использовании иерархии метод гарантирует, что каждый из входящих в список объектов выгрузится не более одного раза, те дубли не выгружаются. Если иерархия не используется, список объектов выгружается как есть.

Типа

Если ПустоеЗначение(ВыбНоменклатура) = 0 Тогда
    _ТекстЗапроса = _ТекстЗапроса + "
    |AND +СпрНоменклатуры.ID IN (SELECT val FROM vt_ТМЦ) ";
    глБазаДанных.УложитьОбъекты(ВыбНоменклатура,"vt_ТМЦ",0,"Номенклатура");
КонецЕсли;

Или я что-то недопонял?...