Используй, когда нужно написать, изменить или оптимизировать запрос 1С, включая пакетные запросы, временные и виртуальные таблицы, обработку NULL, выборку результатов и запрос набора данных СКД.
Scanned 9/28/2026
Install to Claude Code
npx -y skills add mr-ske1r/1c-ai-devstart --skill query-writing --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Query Writing?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/mr-ske1r-query-writing)More formats (shields.io, HTML) on the badges page.
---
name: query-writing
description: "Используй, когда нужно написать, изменить или оптимизировать запрос 1С, включая пакетные запросы, временные и виртуальные таблицы, обработку NULL, выборку результатов и запрос набора данных СКД."
---
# Паттерны запросов 1С
> Нормы кода — в `.claude/rules/1c-rules.md` (единственный источник правил).
> Здесь — развёрнутые паттерны и примеры «как именно».
## Приоритеты
🔴 КРИТИЧНО (нарушение = медленная система): один запрос вместо запросов в цикле; параметры виртуальных таблиц внутри; только нужные поля (не ВЫБРАТЬ *).
🟡 ВАЖНО: временные таблицы для сложных запросов; пакетные операции через ТаблицуЗначений; индексация полей.
🟢 РЕКОМЕНДУЕТСЯ: параметризация; ЕСТЬNULL() при LEFT JOIN; ВЫРАЗИТЬ для составных типов.
---
## Паттерн: форматирование текста запроса
Текст начинается с новой строки после `Запрос.Текст =` без отступа; строки продолжаются через `|`; полям — псевдонимы через `КАК`.
```bsl
Запрос.Текст =
"ВЫБРАТЬ
| Таблица.Поле КАК Поле
|ИЗ
| Таблица";
```
---
## ШАБЛОНЫ КОДА (копируй и адаптируй)
### Шаблон 1: Один запрос вместо цикла
```bsl
// Получаем ВСЕ данные одним запросом
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Ссылка КАК Ссылка,
| Номенклатура.Наименование КАК Наименование,
| Номенклатура.Цена КАК Цена
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| Номенклатура.Ссылка В (&МассивСсылок)";
Запрос.УстановитьПараметр("МассивСсылок", МассивНоменклатуры);
Результат = Запрос.Выполнить();
// Создаём соответствие для быстрого доступа
СоответствиеДанных = Новый Соответствие;
Выборка = Результат.Выбрать();
Пока Выборка.Следующий() Цикл
СоответствиеДанных.Вставить(Выборка.Ссылка,
Новый Структура("Наименование, Цена", Выборка.Наименование, Выборка.Цена));
КонецЦикла;
// Используем в цикле БЕЗ запросов
Для Каждого Строка Из Документ.Товары Цикл
Данные = СоответствиеДанных.Получить(Строка.Номенклатура);
Если Данные <> Неопределено Тогда
Строка.Цена = Данные.Цена;
КонецЕсли;
КонецЦикла;
```
### Шаблон 2: Пакетный запрос с временными таблицами
```bsl
Запрос = Новый Запрос;
Запрос.Текст =
"// Этап 1: Отбираем документы
|ВЫБРАТЬ
| Документ.Ссылка КАК Ссылка,
| Документ.Контрагент КАК Контрагент,
| Документ.Сумма КАК Сумма
|ПОМЕСТИТЬ втДокументы
|ИЗ
| Документ.Реализация КАК Документ
|ГДЕ
| Документ.Дата МЕЖДУ &ДатаНачала И &ДатаОкончания
| И Документ.Проведен
|
|ИНДЕКСИРОВАТЬ ПО
| Контрагент
|;
|
|////////////////////////////////////////////////////////////////////////////////
|// Этап 2: Группируем по контрагентам
|ВЫБРАТЬ
| втДокументы.Контрагент КАК Контрагент,
| СУММА(втДокументы.Сумма) КАК ОбщаяСумма,
| КОЛИЧЕСТВО(РАЗЛИЧНЫЕ втДокументы.Ссылка) КАК КоличествоДокументов
|ПОМЕСТИТЬ втИтоги
|ИЗ
| втДокументы
|СГРУППИРОВАТЬ ПО
| втДокументы.Контрагент
|;
|
|////////////////////////////////////////////////////////////////////////////////
|// Этап 3: Соединяем с остатками
|ВЫБРАТЬ
| втИтоги.Контрагент,
| втИтоги.ОбщаяСумма,
| втИтоги.КоличествоДокументов,
| ЕСТЬNULL(Остатки.СуммаОстаток, 0) КАК Задолженность
|ИЗ
| втИтоги
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.Взаиморасчеты.Остатки КАК Остатки
| ПО втИтоги.Контрагент = Остатки.Контрагент";
Запрос.УстановитьПараметр("ДатаНачала", ДатаНачала);
Запрос.УстановитьПараметр("ДатаОкончания", ДатаОкончания);
Результат = Запрос.Выполнить();
```
### Шаблон 3: Виртуальная таблица с параметрами ВНУТРИ
```bsl
Запрос.Текст =
"ВЫБРАТЬ
| Остатки.Номенклатура,
| Остатки.Склад,
| Остатки.КоличествоОстаток
|ИЗ
| РегистрНакопления.ТоварыНаСкладах.Остатки(
| &ДатаОстатков,
| Номенклатура В (&СписокНоменклатуры)
| И Склад = &Склад
| ) КАК Остатки";
Запрос.УстановитьПараметр("ДатаОстатков", ДатаОстатков);
Запрос.УстановитьПараметр("СписокНоменклатуры", МассивНоменклатуры);
Запрос.УстановитьПараметр("Склад", СкладСсылка);
```
### Шаблон 4: Пакетная обработка через ТаблицуЗначений
```bsl
// Подготавливаем таблицу значений
ТаблицаДанных = Новый ТаблицаЗначений;
ТаблицаДанных.Колонки.Добавить("Штрихкод", Новый ОписаниеТипов("Строка", , Новый КвалификаторыСтроки(13)));
ТаблицаДанных.Колонки.Добавить("Количество", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 3)));
Для Каждого Строка Из ДанныеИмпорта Цикл
НоваяСтрока = ТаблицаДанных.Добавить();
НоваяСтрока.Штрихкод = Строка.Штрихкод;
НоваяСтрока.Количество = Строка.Количество;
КонецЦикла;
// Один запрос обрабатывает все данные
Запрос = Новый Запрос;
Запрос.УстановитьПараметр("ДанныеИмпорта", ТаблицаДанных);
Запрос.Текст =
"ВЫБРАТЬ
| Данные.Штрихкод,
| Данные.Количество
|ПОМЕСТИТЬ втДанные
|ИЗ
| &ДанныеИмпорта КАК Данные
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| Штрихкоды.Номенклатура,
| втДанные.Количество
|ИЗ
| втДанные
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.Штрихкоды КАК Штрихкоды
| ПО втДанные.Штрихкод = Штрихкоды.Штрихкод";
Результат = Запрос.Выполнить();
```
---
## Подробные паттерны (reference)
**Не загружаются автоматически — открой нужный файл инструментом Read по теме задачи.**
| Тема | Файл |
|---|---|
| Структура запроса: временные таблицы, параметризация, только нужные поля, ПЕРВЫЕ N/пагинация, РАЗЛИЧНЫЕ | `references/structure.md` |
| Соединения: варианты замены коррелированного подзапроса, NULL в LEFT JOIN, ПО vs ГДЕ, ВЫРАЗИТЬ для составных типов | `references/joins.md` |
| Производительность: один запрос вместо цикла, виртуальные таблицы регистров, пакетные операции, Выборка vs Выгрузка, индексация | `references/performance.md` |
| Программная сборка текста запроса: комментарии в запросе, подстановка имени таблицы/поля через СтрЗаменить, условное ПОМЕСТИТЬ, пакет из целых запросов | `references/assembly.md` |
---
## Чек-лист запросов
Дополнение к общему «Чек-листу проверки кода» из `.claude/rules/1c-rules.md` — детализация для запросов:
### Структура запроса
- [ ] НЕТ запросов внутри циклов
- [ ] Сложные запросы разбиты на временные таблицы
- [ ] Временные таблицы проиндексированы по полям соединения
- [ ] Используется `МенеджерВременныхТаблиц` для управления жизненным циклом
- [ ] При программной сборке текста каждая часть — синтаксически целый запрос (открывается в конструкторе)
### Параметризация
- [ ] Все значения передаются через параметры (`&Параметр`)
- [ ] Параметры виртуальных таблиц заданы ВНУТРИ таблицы, не в WHERE
### Обработка NULL
- [ ] Используется `ЕСТЬNULL()` для всех полей из LEFT JOIN
- [ ] Условия фильтрации правой таблицы в LEFT JOIN находятся в ON, не в WHERE
- [ ] Арифметические операции защищены от NULL
### Оптимизация
- [ ] Выбираются только нужные поля (нет `ВЫБРАТЬ *`)
- [ ] Используется `ПЕРВЫЕ N` для ограничения результата где нужно
- [ ] Нет `РАЗЛИЧНЫЕ` без необходимости (дубликаты устранены правильным JOIN)
- [ ] Используется `ВЫРАЗИТЬ()` для составных типов при обращении к реквизитам
### Виртуальные таблицы
- [ ] Параметры периода и отбора переданы внутрь виртуальной таблицы
- [ ] Используются правильные виртуальные таблицы (Остатки, ОстаткиИОбороты, СрезПоследних)
- [ ] Отбор по измерениям задан в параметрах виртуальной таблицы
### Пакетные операции
- [ ] Массивы данных передаются через ТаблицуЗначений как параметр
- [ ] Один запрос обрабатывает все элементы массива
- [ ] Результат сохраняется в Соответствие для быстрого доступа в цикле
---
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!