Разработка и Конфигурация · 12 мин
Как перевести запрос SQL в 1С
Как перевести SQL-запрос на язык запросов 1С: соответствие операторов, соединения, группировки, виртуальные таблицы, типичные ошибки и проверка результата.
Разработчики, приходящие в 1С из мира классических баз данных, часто пытаются переносить готовые SQL-запросы напрямую. Это приводит к ошибкам: язык запросов 1С внешне похож на SQL, но работает не с физическими таблицами СУБД, а с объектами метаданных — справочниками, документами, регистрами. Поэтому «перевод» запроса — это не подмена ключевых слов, а перенос логики выборки на другую модель данных.
Хорошая новость в том, что большинство конструкций имеют прямые аналоги: SELECT, WHERE, JOIN, GROUP BY, ORDER BY переводятся почти один в один. Сложности начинаются там, где SQL опирается на хранимые процедуры, оконные функции, подзапросы с LIMIT или прямую работу с датами на уровне СУБД — в 1С для этого существуют собственные механизмы.
Ниже разобран практический порядок перевода: от сопоставления таблиц и полей до соединений, агрегации, виртуальных таблиц и проверки результата через консоль запросов.
Чем язык запросов 1С отличается от SQL
Язык запросов 1С — декларативный диалект, синтаксически близкий к SQL, но обращающийся не к физическим таблицам, а к сущностям конфигурации: Справочник.Номенклатура, Документ.РеализацияТоваровУслуг, РегистрНакопления.ТоварыНаСкладах. Платформа сама преобразует такой запрос в SQL для конкретной СУБД (MS SQL Server, PostgreSQL, Oracle, IBM Db2), и разработчик не управляет этим уровнем напрямую.
Из этого следуют ключевые ограничения. В языке запросов 1С нет INSERT, UPDATE и DELETE — изменение данных выполняется только объектными средствами. Нет хранимых процедур, триггеров, оконных функций и оператора LIMIT — вместо него используется конструкция ПЕРВЫЕ n. Зато есть механизмы, которых нет в чистом SQL: виртуальные таблицы регистров, итоги, разыменование полей через точку.
Практический вывод: перед переводом нужно понять, какие данные запрашивает SQL-запрос, и найти им соответствие в метаданных конфигурации, а не искать одноимённые таблицы в базе.
Сопоставление таблиц и полей
Первый шаг перевода — построить карту соответствия. Возьмите каждую таблицу из секции FROM исходного SQL-запроса и определите, какому объекту конфигурации она соответствует. Обычно справочники и документы маппятся напрямую, а таблицы движений — на регистры накопления или сведений.
Поля переводятся по именам реквизитов, а не по физическим колонкам СУБД. Например, колонка Descr в таблице справочника на уровне СУБД соответствует реквизиту Наименование. Стандартные реквизиты (Ссылка, Код, Дата, Номер, Проведен) доступны без дополнительных соединений, тогда как в SQL для получения связанных данных часто нужен JOIN.
Особенность 1С — разыменование: через точку можно обратиться к реквизиту связанного объекта, например Товары.Номенклатура.Артикул. В SQL аналогичная задача решалась бы соединением с таблицей номенклатуры. Разыменование удобно, но при массовом использовании в условиях и соединениях замедляет запрос — платформа всё равно строит неявные соединения.
| Конструкция SQL | Аналог в 1С | Комментарий |
|---|---|---|
| SELECT ... FROM table | ВЫБРАТЬ ... ИЗ ОбъектМетаданных | Таблица указывается как объект конфигурации |
| WHERE | ГДЕ | Синтаксис условий почти совпадает |
| LEFT / INNER JOIN | ЛЕВОЕ / ВНУТРЕННЕЕ СОЕДИНЕНИЕ | Семантика аналогична |
| GROUP BY + SUM | СГРУППИРОВАТЬ ПО + СУММА | Агрегатные функции совпадают |
| ORDER BY | УПОРЯДОЧИТЬ ПО | Есть также АВТОУПОРЯДОЧИВАНИЕ |
| LIMIT / TOP | ПЕРВЫЕ n | Указывается сразу после ВЫБРАТЬ |
| CASE WHEN | ВЫБОР КОГДА ... ТОГДА ... КОНЕЦ | Полный аналог условного выражения |
| IS NULL | ЕСТЬ NULL | Проверка на неопределённое значение |
Перевод базовой выборки: пример
Рассмотрим типовой SQL-запрос, выбирающий проведённые документы продажи за период с отбором по контрагенту:
SELECT Doc.Number, Doc.Date, Contr.Name, Doc.Total
FROM SalesDoc AS Doc
INNER JOIN Contractors AS Contr ON Contr.ID = Doc.ContractorID
WHERE Doc.Posted = 1 AND Doc.Date BETWEEN @D1 AND @D2
ORDER BY Doc.Date
Эквивалент на языке запросов 1С выглядит так:
ВЫБРАТЬ
Реализация.Номер,
Реализация.Дата,
Реализация.Контрагент.Наименование КАК Контрагент,
Реализация.СуммаДокумента КАК Сумма
ИЗ
Документ.РеализацияТоваровУслуг КАК Реализация
ГДЕ
Реализация.Проведен
И Реализация.Дата МЕЖДУ &НачалоПериода И &КонецПериода
УПОРЯДОЧИТЬ ПО
Реализация.Дата
Обратите внимание на три момента. Во-первых, соединение с контрагентами заменено разыменованием Контрагент.Наименование. Во-вторых, параметры в 1С обозначаются амперсандом (&НачалоПериода), а не @. В-третьих, агрегат «сумма документа» здесь — обычный реквизит, а не результат SUM по табличной части, как это часто бывает в SQL-моделях.
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ ПЕРВЫЕ 10 Номенклатура.Наименование ИЗ Справочник.Номенклатура КАК Номенклатура";
Результат = Запрос.Выполнить().Выгрузить();Соединения и подзапросы
Соединения переводятся почти дословно: INNER JOIN становится ВНУТРЕННИМ СОЕДИНЕНИЕМ, LEFT JOIN — ЛЕВЫМ, условие связи пишется после ПО. Важное отличие — в 1С условие соединения должно быть равенством полей; неравенства и произвольные выражения в секции ПО не поддерживаются так свободно, как в SQL, и сложные условия выносятся в секцию ГДЕ.
Вложенные запросы в 1С допустимы как в секции ИЗ, так и в условиях (В (ВЫБРАТЬ ...)). Однако при переводе многоуровневых подзапросов из SQL стоит оценить, не заменить ли их временными таблицами. Пакетный запрос с временными таблицами (ПОМЕСТИТЬ ВТ) читается проще и часто работает быстрее, потому что платформа материализует промежуточный результат один раз.
Типичный приём при переводе: SQL-подзапрос, вычисляющий максимальную дату документа по контрагенту, в 1С обычно заменяется соединением с виртуальной таблицей или группировкой во временной таблице, а не коррелированным подзапросом — коррелированные подзапросы в 1С существенно медленнее.
- 1Разберите SQL-запрос: выпишите источники данных, условия, соединения, агрегаты
- 2Сопоставьте каждой таблице объект метаданных или виртуальную таблицу регистра
- 3Перепишите выборку: ВЫБРАТЬ, ИЗ, ГДЕ, соединения, СГРУППИРОВАТЬ ПО
- 4Замените переменные на параметры с амперсандом и задайте их через УстановитьПараметр
- 5Проверьте результат в консоли запросов на копии базы и сравните выборку с оригиналом
Группировки, итоги и виртуальные таблицы
Агрегатные функции — СУММА, КОЛИЧЕСТВО, МАКСИМУМ, МИНИМУМ, СРЕДНЕЕ — совпадают по смыслу с SQL. Отличие в иерархических итогах: конструкция ИТОГИ ПО с ОБЩИЕ и ТОЛЬКО ИЕРАРХИЯ не имеет прямого аналога в стандартном SQL (ближайший эквивалент — GROUPING SETS / ROLLUP), и при переводе из SQL такие блоки просто добавляются заново, если нужны промежуточные суммы.
Главная замена SQL-агрегации — виртуальные таблицы регистров. Если в SQL вы группируете таблицу движений, чтобы получить остаток на дату, в 1С вместо этого обращаются к РегистрНакопления.ТоварыНаСкладах.Остатки(&Период, Склад = &Склад). Параметры виртуальной таблицы (период, условия) указываются в скобках — это критично для производительности: отбор внутри виртуальной таблицы выполняется до соединения, а не после.
Для регистров сведений аналогом запросов вида «последнее значение на дату» (в SQL — подзапрос с MAX по периоду или оконная функция ROW_NUMBER) служит виртуальная таблица СрезПоследних, а для первого значения — СрезПервых. Это одна из самых частых замен при переводе аналитических запросов.
Проверка результата и типичные ошибки
Проверять переведённый запрос удобнее всего в консоли запросов на копии рабочей базы: выполните оригинальный SQL на стороне СУБД (если есть доступ) и переведённый запрос в 1С, затем сравните число строк и контрольные суммы по ключевым полям. Совпадение количества записей — минимальный критерий; далее сверьте агрегаты по нескольким случайным группам.
Признаки корректного перевода: одинаковая кардинальность выборок, совпадающие итоговые суммы, отсутствие дублей, которые в SQL отсекались DISTINCT. Если строк в 1С-выборке больше — почти наверняка потеряно условие соединения или разыменование породило декартово произведение через табличную часть.
Отдельный класс проблем — составные типы. В SQL колонка либо NULL, либо значение одного типа. В 1С реквизит составного типа может содержать пустую ссылку другого типа, и сравнение = &Параметр с параметром не того типа молча вернёт пустой результат. При переводе проверяйте типы параметров через ВЫРАЗИТЬ(... КАК ...) там, где это необходимо.
Как проверить результат
Совпадает с исходной SQL-выборкой
Строк больше — потеряно условие соединения или дубли из табличной части
Контрольные итоги по 3–5 группам совпадают
Суммы кратно завышены — декартово произведение
Запрос выполняется за секунды на рабочем объёме
Минуты на копии — отбор не в параметрах виртуальной таблицы
Когда перевод не требуется: прямой доступ к СУБД
В некоторых сценариях переводить запрос не нужно вовсе. Если задача — интеграционная выгрузка, аналитика во внешнем хранилище или разовая миграция, допустимо выполнить SQL-запрос напрямую к базе через ADO или внешние источники данных. Это законный вариант, но с жёсткими ограничениями.
Прямое чтение из таблиц СУБД обходит логику платформы: вы видите физические структуры, имена которых зависят от конфигурации и могут меняться при обновлении. Прямая запись в таблицы СУБД в обход платформы недопустима — она нарушает целостность итогов, последовательности и служебные механизмы, и такие базы снимаются с поддержки.
Для чтения предпочтительнее внешние источники данных или выгрузка через штатные механизмы: язык запросов покрывает подавляющее большинство аналитических задач, а его результат корректно работает с правами доступа (RLS), чего прямой SQL не гарантирует.
Что важно запомнить
Перевод SQL в 1С — это перенос логики на объекты метаданных, а не замена ключевых слов. Основные операторы имеют прямые аналоги, агрегация по регистрам заменяется виртуальными таблицами с параметрами, а результат обязательно сверяется с оригиналом по числу строк и контрольным суммам.
Частые вопросы
Существует ли автоматический конвертер SQL в язык запросов 1С?
Полноценных конвертеров нет: SQL оперирует физическими таблицами, а язык 1С — метаданными, и автоматически установить это соответствие нельзя. Консоль запросов и конструктор помогают собирать запрос по метаданным, но логику переводит разработчик.
Как перевести SQL-запрос с оконными функциями?
Оконных функций в языке запросов 1С нет. Типовые задачи решаются иначе: нумерация строк — обходом выборки в коде, нарастающий итог — запросом с соединением по неравенству или постобработкой, «последнее значение в группе» — виртуальными таблицами СрезПоследних или группировкой с МАКСИМУМ.
Можно ли выполнить произвольный SQL из кода 1С?
К собственной базе — нет, платформа принимает только язык запросов. К внешней базе — да, через COM-соединение с ADO или внешние источники данных, но только для чтения и только к сторонним системам, а не к базе 1С в обход платформы.
Как перевести условие с датами, если в SQL используются функции DATEADD и DATEDIFF?
В 1С есть свои функции работы с датами: ДОБАВИТЬКДАТЕ и РАЗНОСТЬДАТ с указанием единицы измерения (СЕКУНДА, ДЕНЬ, МЕСЯЦ). Также доступны НАЧАЛОПЕРИОДА и КОНЕЦПЕРИОДА для округления дат, что заменяет типовые SQL-приёмы с усечением времени.
Почему переведённый запрос возвращает меньше строк, чем оригинальный SQL?
Чаще всего дело в параметрах составного типа или в неявном отборе: если параметр имеет тип, не совпадающий с типом поля, сравнение не срабатывает. Проверьте типы через ВЫРАЗИТЬ, а также убедитесь, что соединение не стало внутренним там, где в SQL было левое.
Где отлаживать переведённый запрос?
В консоли запросов на копии базы — она показывает текст, параметры и результат таблицей. Для анализа производительности используется технологический журнал с замером событий DBMSSQL, который показывает, какой SQL платформа реально отправила на сервер.