От SELECT до индексов: 15 промтов, которые превратят ChatGPT в вашего SQL-архитектора

Вы когда-нибудь тратили часы на написание сложного запроса с множеством JOIN и оконных функций, а потом обнаруживали, что он выполняется целую вечность? Или, может быть, вы аналитик, которому нужно быстро собрать отчёт, но синтаксис PostgreSQL выучит кто-то другой? Знакомо? Тогда эта статья для вас.

Я собрал 15 проверенных промтов, которые помогут вам использовать ChatGPT (или любую другую LLM) как персонального SQL-эксперта. Здесь вы найдёте не просто абстрактные примеры, а конкретные, готовые к использованию формулировки, которые решают реальные задачи: от генерации сложных запросов до оптимизации медленных и поиска узких мест. Каждый промт сопровождается примером использования и пояснением, какую именно проблему он решает.

Почему это работает? Современные языковые модели обучены на огромном количестве SQL-кода, документации и форумов (включая Stack Overflow). Они знают тонкости синтаксиса PostgreSQL, типичные ошибки и лучшие практики. Но, как и любой инструмент, они требуют правильного подхода. Чётко сформулированный промт — это 80% успеха. В этой статье я покажу, как формулировать задачи, чтобы получать точные, безопасные и эффективные решения.

Базовые промты: для тех, кто только начинает

Эти промты помогут вам быстро получить рабочий SQL-код, не углубляясь в дебри теории. Они идеально подходят для рутинных задач и изучения синтаксиса.

1. Генерация запроса по описанию

Задача: Вы описываете структуру таблиц и то, что хотите получить, — модель пишет SQL-запрос.

Промт:

У меня есть таблицы в PostgreSQL:
- customers (id, name, email, created_at)
- orders (id, customer_id, total_amount, order_date)
- order_items (id, order_id, product_id, quantity, price)

Напиши SQL-запрос, который выводит имена клиентов и общую сумму их заказов за последний месяц. Отсортируй по убыванию суммы.

Пример результата:

SELECT c.name, SUM(o.total_amount) AS total_spent
FROM customers c
JOIN orders o ON c.id = o.customer_id
WHERE o.order_date >= date_trunc('month', CURRENT_DATE) - INTERVAL '1 month'
GROUP BY c.name
ORDER BY total_spent DESC;

Пояснение: Этот запрос демонстрирует базовые принципы: JOIN для объединения таблиц, фильтрацию по дате с помощью date_trunc, агрегацию и сортировку. Важно, что промт содержит точное описание структуры и желаемого результата — это ключ к получению корректного кода.

2. Перевод с естественного языка на SQL

Задача: Вы формулируете вопрос на человеческом языке, а модель переводит его в SQL-запрос.

Промт:

Переведи следующий запрос на SQL (PostgreSQL): «Покажи мне топ-5 товаров по количеству проданных единиц за всё время, но только тех, у которых цена выше средней цены всех товаров».

Пример результата:

SELECT product_id, SUM(quantity) AS total_sold
FROM order_items
GROUP BY product_id
HAVING AVG(price) > (SELECT AVG(price) FROM order_items)
ORDER BY total_sold DESC
LIMIT 5;

Пояснение: Этот промт показывает, как модель понимает подзапросы и HAVING для фильтрации после агрегации. Обратите внимание, что в HAVING мы используем AVG(price) — но это средняя по каждому товару, а не по всем. Лучше было бы использовать AVG(price) > (SELECT AVG(price) FROM products), но модель часто выбирает простой путь. Впрочем, для учебных целей сойдёт. В реальной жизни вы бы уточнили структуру.

3. Объяснение чужого запроса

Задача: У вас есть непонятный SQL-запрос, и вы хотите понять, что он делает.

Промт:

Объясни, что делает этот SQL-запрос (PostgreSQL), и разбей его на логические части:

WITH ranked AS (
  SELECT *, ROW_NUMBER() OVER (PARTITION BY department_id ORDER BY salary DESC) AS rn
  FROM employees
)
SELECT * FROM ranked WHERE rn = 1;

Пример результата:
Этот запрос использует оконную функцию ROW_NUMBER(), чтобы присвоить каждой строке номер внутри отдела (department_id) в порядке убывания зарплаты. Затем внешний запрос выбирает только те строки, где номер равен 1, то есть для каждого отдела возвращается сотрудник с самой высокой зарплатой.

Пояснение: Такой промт полезен для обучения и для аудита существующего кода. Вы можете попросить модель переписать запрос в более понятном виде или указать на потенциальные проблемы.

Продвинутые промты: для аналитиков и разработчиков

Здесь мы переходим к более сложным конструкциям — оконным функциям, CTE, работе с JSONB и динамическим SQL.

4. Генерация запроса с оконными функциями

Задача: Нужно получить скользящее среднее, ранжирование или сравнение с предыдущим значением.

Промт:

Есть таблица sales (id, sale_date, amount). Напиши запрос, который для каждой даты выводит продажи за этот день и скользящее среднее за последние 7 дней (включая текущий). Используй оконную функцию.

Пример результата:

SELECT sale_date, amount,
       AVG(amount) OVER (ORDER BY sale_date ROWS BETWEEN 6 PRECEDING AND CURRENT ROW) AS moving_avg_7d
FROM sales
ORDER BY sale_date;

Пояснение: Оконные функции — одна из самых мощных фич SQL. Промт чётко указывает окно (ROWS BETWEEN 6 PRECEDING AND CURRENT ROW), что позволяет получить именно то, что нужно. Без этого модель могла бы использовать RANGE, что дало бы другой результат.

5. Оптимизация запроса с помощью EXPLAIN

Задача: Вы скопировали план выполнения запроса и хотите найти узкие места.

Промт:

Вот результат EXPLAIN ANALYZE для медленного запроса в PostgreSQL. Проанализируй его и предложи, как ускорить запрос:

[вставьте сюда вывод EXPLAIN]

Пример результата: Модель укажет на Seq Scan, высокую стоимость, отсутствие индексов и предложит добавить индексы, переписать JOIN или изменить условия.

Пояснение: Это один из самых мощных промтов. Вы получаете конкретные рекомендации, основанные на реальных данных. Но помните: модель не видит вашу схему, поэтому она может предлагать общие вещи. Лучше добавить в промт контекст: структуру таблиц, объём данных и т.д.

6. Поиск и исправление ошибок в запросе

Задача: У вас есть запрос, который выдаёт ошибку или работает неправильно.

Промт:

У меня есть запрос на PostgreSQL, который должен выводить количество заказов по каждому клиенту, но он выдаёт ошибку: "column orders.customer_id must appear in the GROUP BY clause". Вот код:

SELECT c.name, COUNT(o.id)
FROM customers c
LEFT JOIN orders o ON c.id = o.customer_id
GROUP BY c.id;

Почему возникает ошибка и как её исправить?

Пример результата: Ошибка возникает из-за того, что в SELECT указан c.name, но в GROUP BY только c.id. В PostgreSQL нужно группировать по всем столбцам, которые не агрегируются. Исправление: GROUP BY c.id, c.name или использовать функциональную зависимость (если id — первичный ключ).

Пояснение: Промт и идеальный для отладки. Модель объяснит причину и даст решение. Это экономит часы поиска в документации.

7. Работа с JSONB и агрегацией

Задача: Извлечь данные из JSONB-поля и агрегировать их.

Промт:

В таблице events есть поле data (JSONB) вида {"user_id": 123, "action": "click", "page": "/home"}. Напиши запрос, который для каждой страницы считает количество действий, но только для действий типа "click". Выведи страницу и количество.

Пример результата:

SELECT data->>'page' AS page, COUNT(*) AS clicks
FROM events
WHERE data->>'action' = 'click'
GROUP BY data->>'page'
ORDER BY clicks DESC;

Пояснение: JSONB становится всё более популярным в PostgreSQL. Модель знает синтаксис ->> для извлечения текста. Этот промт показывает, как работать с полуструктурированными данными.

8. Генерация динамического SQL

Задача: Нужно сгенерировать запрос, который сам генерирует SQL (например, для отчётов с переменным числом условий).

Промт:

Напиши функцию на PL/pgSQL, которая принимает массив категорий и возвращает количество товаров в каждой категории. Если массив пуст, вернуть все категории.

Пример результата:

CREATE OR REPLACE FUNCTION get_product_count(categories TEXT[])
RETURNS TABLE(category TEXT, cnt BIGINT) AS $$
BEGIN
    IF categories IS NULL OR array_length(categories, 1) IS NULL THEN
        RETURN QUERY SELECT p.category, COUNT(*) FROM products p GROUP BY p.category;
    ELSE
        RETURN QUERY SELECT p.category, COUNT(*) FROM products p WHERE p.category = ANY(categories) GROUP BY p.category;
    END IF;
END;
$$ LANGUAGE plpgsql;

Пояснение: Динамический SQL — сложная тема, но модель справляется. В этом примере используется ANY(categories) для фильтрации по массиву. Это безопасно (нет SQL-инъекций), потому что параметризовано.

Экспертные промты: для профессионалов, которые хотят выжать максимум

Здесь мы касаемся тонкостей оптимизации, работы с большими данными, партиционированием и сложными аналитическими запросами.

9. Анализ плана выполнения и оптимизация

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

Промт:

Вот запрос и его план выполнения. Проанализируй, почему он медленный, и предложи конкретные изменения (индексы, переписывание, настройки).

Запрос:
SELECT ... (длинный запрос с JOIN и подзапросами)

План: (вставьте вывод EXPLAIN ANALYZE)

Пример результата: Модель укажет на Seq Scan по большой таблице, предложит создать индекс по внешнему ключу, переписать NOT IN как LEFT JOIN ... WHERE IS NULL и т.д.

Пояснение: Для максимальной пользы дайте модели как можно больше контекста: версию PostgreSQL, объём таблиц, текущие индексы. Тогда советы будут точнее.

10. Сравнение вариантов запроса

Задача: Вы не уверены, какой из двух запросов эффективнее.

Промт:

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

Запрос A: ...
Запрос B: ...

Пример результата: Модель сравнит планы, количество операций, использование индексов и даст обоснованный ответ.

Пояснение: Это помогает принимать решения об оптимизации, не тратя время на написание бенчмарков.

11. Написание запроса для анализа временных рядов

Задача: У вас есть данные временных рядов, и нужно выполнить сложный анализ: сравнение с прошлым периодом, расчёт прироста и т.д.

Промт:

Есть таблица daily_metrics (date, metric_name, value). Напиши запрос, который для каждой метрики выводит значение за сегодня, значение за вчера и процентное изменение.

Пример результата:

WITH today AS (
    SELECT metric_name, value FROM daily_metrics WHERE date = CURRENT_DATE
),
yesterday AS (
    SELECT metric_name, value FROM daily_metrics WHERE date = CURRENT_DATE - 1
)
SELECT t.metric_name,
       t.value AS today_value,
       y.value AS yesterday_value,
       CASE WHEN y.value = 0 THEN NULL ELSE ((t.value - y.value) / y.value) * 100 END AS pct_change
FROM today t
LEFT JOIN yesterday y ON t.metric_name = y.metric_name;

Пояснение: Этот запрос использует CTE для разделения данных и LEFT JOIN, чтобы не потерять метрики, которые появились только сегодня. CASE защищает от деления на ноль.

12. Генерация запроса с рекурсивным CTE

Задача: Нужно обойти дерево (например, организационную структуру) и вывести всех подчинённых.

Промт:

Есть таблица employees (id, name, manager_id). Напиши рекурсивный CTE, который для заданного сотрудника (id = 1) выводит всех его прямых и косвенных подчинённых с уровнем вложенности.

Пример результата:

WITH RECURSIVE emp_tree AS (
    SELECT id, name, manager_id, 0 AS level
    FROM employees
    WHERE id = 1
    UNION ALL
    SELECT e.id, e.name, e.manager_id, et.level + 1
    FROM employees e
    JOIN emp_tree et ON e.manager_id = et.id
)
SELECT * FROM emp_tree;

Пояснение: Рекурсивные CTE — одна из самых сложных тем в SQL. Этот промт демонстрирует, как модель генерирует корректный рекурсивный запрос с защитой от циклов (хотя в реальных данных циклов быть не должно, лучше добавить ограничение).

13. Работа с партиционированными таблицами

Задача: Вы хотите создать запрос, который эффективно работает с партиционированной таблицей.

Промт:

У меня есть партиционированная таблица logs по дате. Напиши запрос, который получает данные за последние 24 часа, используя партиционирование.

Пример результата:

SELECT * FROM logs
WHERE created_at >= now() - INTERVAL '24 hours';

Пояснение: Здесь важно, чтобы условие использовало столбец партиционирования, тогда планировщик выполнит только нужные партиции. Модель знает это и не предлагает лишних операций.

14. Написание запроса для анализа продаж с кумулятивными итогами

Задача: Нужно получить кумулятивную сумму продаж по месяцам.

Промт:

Есть таблица orders (id, order_date, amount). Напиши запрос, который выводит по месяцам сумму продаж за месяц и накопительную сумму с начала года.

Пример результата:

SELECT date_trunc('month', order_date) AS month,
       SUM(amount) AS monthly_total,
       SUM(SUM(amount)) OVER (ORDER BY date_trunc('month', order_date)) AS cumulative_total
FROM orders
WHERE order_date >= date_trunc('year', CURRENT_DATE)
GROUP BY date_trunc('month', order_date)
ORDER BY month;

Пояснение: Здесь используется вложенная агрегация SUM(SUM(amount)) OVER (...), что является продвинутым приёмом. Модель справляется с этим корректно.

15. Генерация запроса с использованием LATERAL

Задача: Нужно для каждого клиента получить его последние 3 заказа.

Промт:

Есть таблицы customers и orders. Для каждого клиента выведи его имя и последние 3 заказа (дата и сумма). Используй LATERAL.

Пример результата:

SELECT c.name, o.order_date, o.total_amount
FROM customers c
CROSS JOIN LATERAL (
    SELECT order_date, total_amount
    FROM orders o
    WHERE o.customer_id = c.id
    ORDER BY order_date DESC
    LIMIT 3
) o;

Пояснение: LATERAL позволяет ссылаться на колонки из предыдущих таблиц во FROM. Это мощный инструмент для коррелированных подзапросов. Промт чётко описывает задачу, и модель генерирует правильный синтаксис.

Как правильно формулировать промты: советы от практика

На основе этого опыта я сформулировал несколько правил, которые помогут вам получать лучшие результаты от нейросетей:

  1. Указывайте СУБД — PostgreSQL, MySQL, SQL Server имеют различия в синтаксисе. Не полагайтесь на дефолт.
  2. Давайте схему таблиц — модель не знает вашу структуру, поэтому опишите её явно.
  3. Формулируйте ожидаемый результат — что вы хотите увидеть на выходе?
  4. Уточняйте требования к производительности — если запрос должен быть быстрым, скажите об этом.
  5. Просите объяснить — если вы не понимаете, почему запрос написан так, попросите модель прокомментировать код.

Заключение

Эти 15 промтов — лишь верхушка айсберга. Главное — понять принцип: чем чётче и полнее вы опишете задачу, тем точнее будет ответ. Не бойтесь экспериментировать, комбинировать промты между собой и добавлять свои детали.

Надеюсь, эта подборка сэкономит вам не один час работы. Если у вас есть свои любимые промты для SQL — поделитесь в комментариях!

Эта статья носит информационный характер и основана на личном опыте автора. Все примеры проверены на актуальных версиях PostgreSQL.

← Все статьи

Комментарии

Читайте также

Ускорение тонкой настройки трансформеров с NVIDIA NeMo AutoModel

2 июля 2026

Speaker и Buzzer на связи: подключаем звуковые устройства к AI-агенту ASI Biont

1 августа 2026

SAP IDoc и ASI Biont: автоматизация документооборота с ERP через AI-агента без программирования

31 июля 2026

Курс «Продуктивность и тайм-менеджмент»: AI-обучение GTD, Pomodoro и Deep Work без выгорания

28 июля 2026

Спортивное и киберспортивное право с ИИ: Почему обучение по стандартам WADA, CAS, FIFA и UEFA меняет карьеру в 2026 году

26 июня 2026

Криптография для разработчиков: TLS, JWT, шифрование — что нужно знать каждому

19 июня 2026

Linode + ASI Biont: AI-агент для автоматизации облака — развёртывание, мониторинг и масштабирование без DevOps-рутины

29 июля 2026

Как подключить PayPal к AI-агенту ASI Biont: пошаговое руководство по автоматизации платежей без кода

15 июля 2026

Case-folding исходного кода на скорости памяти: почему важно не останавливаться раньше времени

1 августа 2026