Почему «напиши запрос» — стратегия проигрыша
DeepSeek и прочие LLM обучены на миллионах примеров SQL. Они идеально знают синтаксис WINDOW FUNCTIONS, CTE и оптимизаторы. Но они не видят вашу базу: ни названий таблиц, ни типов колонок, ни внешних ключей, ни бизнес-логики «почему status=3 значит «отменён»».
Когда вы пишете «сделай отчёт по продажам», модель подставляет среднестатистические имена: sales, orders, amount. В реальности у вас fct_orders_dwh, gmv_rub и партиционирование по dt. Результат — красивый, но нерабочий код.
Вывод: качество SQL на 90% зависит от контекста, который вы подаёте. Промпт — это не вопрос, это техническое задание.
Анатомия промышленного промпта: 5 обязательных блоков
1. Роль и экспертиза
Задайте персону: Senior Data Analyst, эксперт по ClickHouse / PostgreSQL / Snowflake. Это включает в моделировании лучшие практики: CTE вместо подзапросов, явные колонки вместо SELECT *, аннотации типов.
2. Схема и контекст (DDL)
Самый критичный блок. Передавайте CREATE TABLE для всех участвующих таблиц. Укажите партиции, индексы, семантику enum-полей (status: 1=new, 2=paid, 3=cancelled). DeepSeek поддерживает длинный контекст — используйте это.
3. Чёткая задача и метрики
Не «отчёт по продажам», а «Топ-20 SKU по GMV (сумма gmv_rub) за последние 30 календарных дней, только заказы в статусе delivered, с разбивкой по категориям 1-го уровня» . Числа, фильтры, гранулярность — без двусмысленностей.
4. Ограничения
Диалект (ClickHouse, Postgres, BigQuery), лимиты выполнения (LIMIT 10000), запреты (без подзапросов в SELECT), требования к производительности (использовать индекс idx_dt_status).
5. Формат ответа
Требуйте: «Код в markdown-блоке с языком sql», «Комментарии к каждому CTE», «Объяснение плана запроса после кода», «Нет вводного текста, только код». Это экономит время на пост-обработке.
Библиотека паттернов: готовые рецепты для частых задач
Генерация из DDL
Передайте DDL 3-5 таблиц. Задача: «Напиши запрос для метрики X». Модель сама найдёт ключи JOIN и напишет корректный SQL.
-- Контекст: DDL tables
-- Задача: Доля повторных покупателей за 90 дней
-- Диалект: PostgreSQLОптимизация медленного запроса
Пришлите EXPLAIN ANALYZE и сам запрос. Просьба: «Убери Seq Scan, используй индекс idx_user_dt, перепиши через CTE для читаемости».
-- Вход: EXPLAIN + SQL
-- Цель: cost < 1000, нет Seq Scan
-- Вывод: оптимизированный SQL + разбор измененийМиграция диалектов
«Переведи этот T-SQL в ClickHouse SQL. Замени GETDATE() на now(), TOP 10 на LIMIT 10, разверни PIVOT через if/countIf».
-- Источник: T-SQL (MS SQL)
-- Целевой: ClickHouse
-- Сохрани логику оконных фукнцийГенерация тестов (dbt / unit)
«Сгенерируй yml для dbt tests: not_null для PK, unique для id, accepted_values для status, relationships к dim_tables. Плюс unit-test с моками входных данных и ожидаемым результатом».
version: 2
models:
- name: fct_orders
columns:
- name: order_id
tests: [unique, not_null]Разбор ошибки выполнения
Скиньте текст ошибки БД. «Ошибка: Column «user_id» not found in GROUP BY. Исправь запрос, сохранив логику». Модель сам поправит агрегацию.
ERROR: column "u.id" must appear in GROUP BY
-- Fix: add u.id to GROUP BY or aggregateДокументирование легаси
«Объясни этот запрос 200 строк пошагово: какие таблицы, какие бизнес-правила в WHERE, что считают оконные функции. Выдай markdown с разделами: Вход, Логика, Выход, Риски».
-- Вход: старый SQL
-- Вывод: README.md для репозитория
-- Фокус: бизнес-смысл, не синтаксисОсобенности DeepSeek: Reasoning Mode и длинный контекст
Включайте DeepThink (R1)
Для сложных аналитических запросов (вложенные CTE, оконные функции, рекурсия) включайте режим рассуждений. Модель покажет цепочку: «Сначала найду ключи JOIN, потом проверю партиции, потом напишу CTE». Это позволяет отловить ошибки логики до генерации кода.
Корми полную схему, а не выжимку
Окно контекста DeepSeek позволяет передать DDL 20-30 таблиц. Не экономьте токены на схеме. Полная схема устраняет галлюцинации имен колонок и типов данных. Если схема огромна — передавайте только релевантные таблицы, но с полным DDL (включая комментарии к колонкам, если есть).
Разбор ошибок: мифы, которые стоят часов отладки
Миф: «Модель сама поймёт смысл колонок»
Реальность: user_type может быть enum (1,2,3) или строками (\’b2b\’,\’b2c\’). Без словаря модель угадает неправильно в 50% случаев. Всегда давайте маппинг значений.
Миф: «Она знает специфику моего движка»
Реальность: ClickHouse не поддерживает MERGE, Postgres не имеет ARRAY JOIN, BigQuery требует проект.датасет.таблица. Явно прописывайте диалект в блоке «Ограничения».
Миф: «Один промпт — готовый продакшн-код»
Реальность: Итерации — это норма. Первый вариант: структура. Второй: фикс типов. Третий: оптимизация под EXPLAIN. Четвёртый: тесты. Работайте в диалоге, а не в режиме «одно поколение».
Миф: «Промптинг — это магия, не инженерия»
Реальность: Промпт — это код на естественном языке. Он требует версионирования, код-ревью, модульности (подключаемые сниппеты со схемами) и CI-проверок (запуск сгенерированного SQL в тестовой БД).
Универсальный шаблон: копируйте, вставляйте DDL, получайте результат
Итеративный цикл: диалог вместо монолога
Вы: Присылаете DDL + шаблон выше. Получаете v1.
Вы: «Проверь: в dim_skus категория называется category_l1, а не category. Исправь JOIN. Добавь фильтр is_active=1».
Вы: Кидаете EXPLAIN v2. «Убери Seq Scan на fct_orders. Есть индекс (user_id, dt). Перепиши».
Вы: «Сгенерируй dbt unit-test с моками: 3 заказа, 2 delivered, 1 cancelled. Ожидаемый результат: 2 строки». Запускаете тест локально.
Итог: Готовый, протестированный, понятный SQL, который не упадёт на продакшене после добавления колонки в таблицу.