Вы когда-нибудь тратили полдня на, казалось бы, простой SQL-запрос, который в итоге оказывался медленнее, чем ожидание ответа от техподдержки? А может, вы часами расшифровывали чужие (или свои собственные) запросы, написанные в спешке и без комментариев? Если да — эта статья для вас. Я — аналитик данных с десятилетним стажем, и последние два года я активно использую большие языковые модели (LLM) в своей повседневной работе. За это время я выработал десятки промтов, которые превратили ChatGPT и аналоги из «просто болтушки» в мощный инструмент, реально экономящий часы работы с базами данных. В этой подборке я поделюсь 12 самыми эффективными промтами, сгруппированными по сложности: от простых помощников до продвинутых оптимизаторов. Но предупреждаю: я не буду учить вас основам SQL — предполагаю, что вы уже умеете писать SELECT, JOIN и GROUP BY. Моя цель — показать, как с помощью правильно сформулированных промтов выжать максимум из LLM и решать задачи, которые раньше требовали глубокой экспертизы, в разы быстрее.
Базовые промты: ежедневная рутина под контролем
Начнём с простых, но невероятно полезных промтов, которые пригодятся каждому, кто работает с SQL ежедневно. Они помогают быстро генерировать запросы по описанию на естественном языке, объяснять сложный код и переводить запросы между диалектами SQL.
1. Генерация запроса по описанию на естественном языке
Задача: Быстро получить рабочий SQL-запрос, когда вы знаете, что нужно сделать, но не хотите тратить время на синтаксис и join'ы.
Промт:
Напиши SQL-запрос для PostgreSQL, который выводит список клиентов, сделавших более 5 заказов за последние 30 дней. Таблицы: customers (id, name, email), orders (id, customer_id, created_at). В результатах должны быть имя клиента и количество заказов, отсортировано по убыванию количества.
Пример результата:
SELECT c.name, COUNT(o.id) AS order_count
FROM customers c
JOIN orders o ON c.id = o.customer_id
WHERE o.created_at >= NOW() - INTERVAL '30 days'
GROUP BY c.id, c.name
HAVING COUNT(o.id) > 5
ORDER BY order_count DESC;
Как это экономит время: Вместо того чтобы вручную вспоминать синтаксис HAVING, JOIN и INTERVAL, вы получаете готовый запрос за 10 секунд. Остаётся только проверить его на тестовых данных. Важно: всегда указывайте диалект SQL (PostgreSQL, MySQL, SQLite и т.д.), потому что синтаксис различается.
2. Объяснение сложного запроса «на пальцах»
Задача: Понять, что делает чужой (или ваш собственный, но забытый) сложный запрос с множеством подзапросов и оконных функций.
Промт:
Объясни, что делает этот SQL-запрос для PostgreSQL. Разбей его на шаги и для каждого шага объясни, что происходит, простым языком.
WITH ranked AS (
SELECT *, ROW_NUMBER() OVER (PARTITION BY customer_id ORDER BY created_at DESC) AS rn
FROM orders
)
SELECT * FROM ranked WHERE rn = 1;
Пример результата:
Этот запрос находит последний заказ каждого клиента. Разбивка:
1. CTE (Common Table Expression) 'ranked' создаёт временную таблицу, где каждой строке присваивается номер (rn) внутри группы заказов одного клиента, начиная с 1 для самого свежего заказа (ORDER BY created_at DESC).
2. Внешний запрос выбирает только те строки, где rn = 1, т.е. только последние заказы каждого клиента.
Как это экономит время: Вместо того чтобы мысленно выполнять запрос, вы получаете чёткое объяснение, которое можно быстро проверить и использовать для дальнейшей работы.
3. Перевод запроса с одного диалекта на другой
Задача: Перенести запрос из MySQL в PostgreSQL или наоборот, не переписывая вручную.
Промт:
Переведи этот SQL-запрос с MySQL на PostgreSQL. Учти различия в функциях, типах данных и синтаксисе.
SELECT DATE_FORMAT(created_at, '%Y-%m') AS month, COUNT(*) FROM orders GROUP BY month;
Пример результата:
SELECT TO_CHAR(created_at, 'YYYY-MM') AS month, COUNT(*) FROM orders GROUP BY month;
Как это экономит время: При миграции между СУБД часто всплывают мелкие различия. Вместо того чтобы гуглить каждую функцию, вы получаете готовый перевод. Но всегда проверяйте результат, потому что LLM может не учесть все нюансы.
Продвинутые промты: когда нужно не просто написать, а оптимизировать
Переходим к более сложным задачам: оптимизация медленных запросов, поиск ошибок и написание сложных аналитических выборок.
4. Оптимизация медленного запроса
Задача: Ускорить запрос, который выполняется слишком долго.
Промт:
У меня есть медленный запрос в PostgreSQL. Вот его план выполнения (EXPLAIN ANALYZE). Подскажи, как его ускорить: какие индексы создать, как переписать запрос. Приведи конкретные рекомендации.
EXPLAIN ANALYZE SELECT * FROM orders JOIN customers ON orders.customer_id = customers.id WHERE customers.country = 'RU';
План: Seq Scan on customers (cost=0.00..1000.00 rows=5000 width=100) ... (приведи реальный вывод)
Пример результата:
Вижу, что используется полное сканирование таблицы customers (Seq Scan). Рекомендации:
1. Создайте индекс на колонке customers.country: CREATE INDEX idx_customers_country ON customers(country);
2. Если таблица orders большая, убедитесь, что есть индекс на orders.customer_id: CREATE INDEX idx_orders_customer_id ON orders(customer_id);
3. Перепишите запрос с использованием EXISTS, если нужно только проверить наличие, но не выбирать данные из orders.
Как это экономит время: Вместо того чтобы разбираться в тонкостях выполнения запроса вручную, вы получаете готовые рекомендации, которые можно сразу применить. Обязательно просите LLM анализировать план выполнения, а не только текст запроса — это даёт более точные советы.
5. Поиск и исправление ошибок в запросе
Задача: Найти синтаксическую или логическую ошибку в запросе.
Промт:
Этот SQL-запрос для PostgreSQL выдает ошибку: ERROR: column "o.total" must appear in the GROUP BY clause or be used in an aggregate function. Исправь запрос.
SELECT c.name, o.total FROM customers c JOIN orders o ON c.id = o.customer_id GROUP BY c.name;
Пример результата:
Ошибка возникает потому, что колонка o.total не включена в GROUP BY и не используется в агрегатной функции. Исправленный запрос:
SELECT c.name, SUM(o.total) AS total_sum FROM customers c JOIN orders o ON c.id = o.customer_id GROUP BY c.name;
Как это экономит время: Вместо того чтобы читать документацию и разбираться в правилах GROUP BY, вы получаете исправленный вариант и объяснение ошибки.
6. Генерация случайных тестовых данных
Задача: Создать набор синтетических данных для проверки запроса.
Промт:
Сгенерируй 10 INSERT-запросов для таблицы employees (id, name, salary, department_id) в PostgreSQL. Используй разные имена и зарплаты в диапазоне 30000-100000, department_id от 1 до 5.
Пример результата:
INSERT INTO employees (id, name, salary, department_id) VALUES
(1, 'Иван Петров', 45000, 2),
(2, 'Мария Смирнова', 60000, 3),
(3, 'Петр Сидоров', 35000, 1),
(4, 'Ольга Кузнецова', 80000, 4),
(5, 'Алексей Иванов', 50000, 2),
(6, 'Елена Соколова', 70000, 5),
(7, 'Дмитрий Морозов', 42000, 1),
(8, 'Наталья Волкова', 55000, 3),
(9, 'Сергей Николаев', 90000, 4),
(10, 'Анна Зайцева', 38000, 5);
Как это экономит время: Когда нужно быстро проверить логику запроса, не хочется вручную придумывать данные. Этот промт помогает сгенерировать правдоподобные данные за секунды.
7. Написание сложного аналитического запроса с оконными функциями
Задача: Получить скользящее среднее или другие вычисления с оконными функциями.
Промт:
Напиши SQL-запрос для PostgreSQL, который для каждого дня выводит дату, количество заказов и скользящее среднее за последние 7 дней (включая текущий). Таблица orders: id, created_at, amount.
Пример результата:
SELECT
created_at::date AS day,
COUNT(*) AS order_count,
AVG(COUNT(*)) OVER (ORDER BY created_at::date ROWS BETWEEN 6 PRECEDING AND CURRENT ROW) AS moving_avg_7d
FROM orders
GROUP BY created_at::date
ORDER BY day;
Как это экономит время: Оконные функции — мощный, но сложный инструмент. Промт избавляет от необходимости вспоминать синтаксис ROWS BETWEEN и т.д.
Экспертные промты: для сложных сценариев и нестандартных задач
Теперь переходим к самым мощным промтам, которые могут заменить целого DBA. Они требуют понимания внутренностей баз данных и умения грамотно формулировать контекст.
8. Анализ плана выполнения и поиск узких мест
Задача: Используя EXPLAIN ANALYZE, найти причину медленной работы запроса и предложить конкретные меры.
Промт:
Вот план выполнения запроса в PostgreSQL (EXPLAIN ANALYZE). Проанализируй его, найди узкие места (большие затраты, Seq Scan на больших таблицах, неэффективные Join) и дай рекомендации по оптимизации.
[Вставьте реальный вывод EXPLAIN ANALYZE]
Пример результата:
Анализ плана:
- Узел Seq Scan on orders занимает 80% времени — необходимо создать индекс на колонке customer_id.
- Hash Join в целом эффективен, но можно попробовать увеличить work_mem для ускорения.
- Рекомендации: CREATE INDEX idx_orders_customer_id ON orders(customer_id);
- Проверьте, не дублируются ли данные в таблице (ANALYZE).
Как это экономит время: Вместо того чтобы вручную интерпретировать план, вы получаете готовый разбор и рекомендации. Это особенно полезно для начинающих, которые ещё не умеют читать планы.
9. Автоматическая документация схемы базы данных
Задача: Сгенерировать описание схемы базы данных для документации или онбординга новых разработчиков.
Промт:
Предоставь схему базы данных в виде SQL команд CREATE TABLE для PostgreSQL. Создай для каждой таблицы краткое описание на русском языке в комментариях. Вот список таблиц: users, orders, products, order_items.
Пример результата:
-- Таблица пользователей
CREATE TABLE users (
id SERIAL PRIMARY KEY,
name VARCHAR(100),
email VARCHAR(255) UNIQUE
);
-- Таблица заказов
CREATE TABLE orders (
id SERIAL PRIMARY KEY,
user_id INT REFERENCES users(id),
created_at TIMESTAMP DEFAULT NOW()
);
-- Таблица товаров
CREATE TABLE products (
id SERIAL PRIMARY KEY,
name VARCHAR(255),
price DECIMAL(10,2)
);
-- Таблица позиций заказа
CREATE TABLE order_items (
order_id INT REFERENCES orders(id),
product_id INT REFERENCES products(id),
quantity INT
);
Как это экономит время: Вместо того чтобы писать документацию вручную, вы получаете готовый комментарий к каждой таблице. Это особенно полезно для поддержки легаси-систем.
10. Генерация запросов для анализа данных с временными рядами
Задача: Создать запрос для расчёта метрик типа DAU/WAU/MAU или retention.
Промт:
Напиши запрос для PostgreSQL, который вычисляет DAU (Daily Active Users) за последние 30 дней. Таблица user_activity: user_id, activity_date. Выведи дату и количество уникальных пользователей.
Пример результата:
SELECT activity_date AS date, COUNT(DISTINCT user_id) AS dau
FROM user_activity
WHERE activity_date >= CURRENT_DATE - INTERVAL '30 days'
GROUP BY activity_date
ORDER BY date;
Как это экономит время: Аналитики часто пишут такие запросы, и промт позволяет сэкономить время на синтаксисе.
11. Объяснение разницы между JOIN'ами с примерами
Задача: Понять разницу между INNER, LEFT, RIGHT, FULL JOIN на конкретном примере.
Промт:
Объясни разницу между INNER JOIN, LEFT JOIN, RIGHT JOIN и FULL JOIN на примере двух таблиц: employees (id, name) и departments (id, name). Покажи пример запроса и результат для каждого типа JOIN.
Пример результата:
Пусть employees: (1, 'Иван', 1), (2, 'Мария', 2), (3, 'Петр', NULL)
departments: (1, 'IT'), (2, 'Sales'), (3, 'HR')
INNER JOIN: вернет только сотрудников с отделом (Иван-IT, Мария-Sales).
LEFT JOIN: все сотрудники, даже без отдела (Петр-NULL).
RIGHT JOIN: все отделы, даже без сотрудников (HR).
FULL JOIN: все строки из обеих таблиц.
Как это экономит время: Вместо того чтобы мысленно моделировать, вы получаете наглядный пример.
12. Написание хранимой процедуры или функции
Задача: Создать хранимую функцию на PL/pgSQL для повторяющегося действия.
Промт:
Напиши функцию на PL/pgSQL, которая принимает customer_id и возвращает сумму всех его заказов. Если клиент не найден, вернуть 0.
Пример результата:
CREATE OR REPLACE FUNCTION get_customer_total(cust_id INT)
RETURNS NUMERIC AS $$
DECLARE
total NUMERIC;
BEGIN
SELECT SUM(o.amount) INTO total
FROM orders o
WHERE o.customer_id = cust_id;
IF total IS NULL THEN
RETURN 0;
ELSE
RETURN total;
END IF;
END;
$$ LANGUAGE plpgsql;
Как это экономит время: Функции сложно писать с нуля, а промт даёт рабочий каркас.
Заключение
Эти 12 промтов — лишь вершина айсберга. Главное — понять принцип: чем больше контекста вы даёте LLM, тем точнее и полезнее будет ответ. Указывайте диалект SQL, структуру таблиц, примеры данных и ожидаемый результат. Но помните: LLM — не замена экспертизе, а инструмент. Всегда проверяйте сгенерированный код на тестовых данных и не полагайтесь слепо на ответы. Используйте промты как ускоритель, а не как костыль. Начните с базовых промтов из нашей подборки и постепенно переходите к экспертным. И не забывайте: лучший способ освоить что-то — практика. Откройте свой любимый SQL-клиент и попробуйте применить хотя бы один промт из списка прямо сегодня. Уверен, вы почувствуете разницу. Если у вас есть свои любимые промты — делитесь в комментариях, будем собирать коллекцию!
Комментарии