Вы когда-нибудь тратили часы на отладку медленного SQL-запроса, чтобы в итоге найти одну пропущенную запятую? Или мучительно вспоминали синтаксис сложного LATERAL JOIN? Добро пожаловать в клуб. Но хорошая новость: современные LLM, такие как ChatGPT, могут стать вашим персональным ассистентом по базам данных, если правильно составить промт. В этой статье я поделюсь 12 проверенными шаблонами, которые превратят ChatGPT в DBA-аналитика. Каждый промт протестирован на реальных примерах из PostgreSQL и MySQL, так что вы можете использовать их сразу, адаптируя под свои задачи.
1. Генерация сложных JOIN-запросов
Задача: Получить SQL-запрос, объединяющий несколько таблиц с неочевидными связями.
Промт:
Напиши SQL-запрос для PostgreSQL, который объединяет таблицы users, orders и order_items. Нужно вывести: имя пользователя, общую сумму его заказов за последний месяц, и количество купленных товаров. Учти, что таблица users имеет поля id, name; orders — id, user_id, created_at, total; order_items — order_id, product_name, quantity. Используй LEFT JOIN, чтобы включить пользователей без заказов.
Пример результата:
SELECT
u.name,
COALESCE(SUM(o.total), 0) AS total_spent,
COUNT(oi.id) AS items_count
FROM users u
LEFT JOIN orders o ON u.id = o.user_id
AND o.created_at >= NOW() - INTERVAL '1 month'
LEFT JOIN order_items oi ON o.id = oi.order_id
GROUP BY u.id, u.name;
Разбор: Промт четко описывает структуру таблиц, тип JOIN и требуемые агрегаты. Это снижает вероятность ошибок и лишних догадок.
2. Оптимизация медленных запросов
Задача: Улучшить производительность существующего запроса.
Промт:
Вот запрос для MySQL, который выполняется 15 секунд. Проанализируй его и предложи оптимизации: индексы, переписывание, изменение структуры.
SELECT * FROM products WHERE category_id = 5 AND price > 100 ORDER BY created_at DESC;
Пример результата:
Рекомендации:
1. Создать составной индекс (category_id, price, created_at) для покрытия запроса.
2. Заменить SELECT * на перечисление нужных колонок.
3. Если нужна только последняя страница, добавить LIMIT.
Предлагаемый индекс:
CREATE INDEX idx_products_category_price_created ON products (category_id, price, created_at DESC);
Вывод: Четкое описание проблемы и контекста (СУБД, время выполнения) помогает модели дать точные советы.
3. Анализ плана выполнения
Задача: Интерпретировать вывод EXPLAIN.
Промт:
Я выполнил EXPLAIN ANALYZE для PostgreSQL, вот результат:
[вставьте вывод]
Объясни, что означает каждый узел, где узкое место, и как исправить.
Пример результата:
Узел Seq Scan on orders (cost=0.00..1000.00 rows=10000) — это полное сканирование таблицы, что медленно при больших объемах. Узкое место — отсутствие индекса на status. Рекомендую создать индекс: CREATE INDEX idx_orders_status ON orders(status); Также обратите внимание на Hash Join — проверьте, достаточно ли памяти для hash-таблицы.
Совет: Всегда вставляйте полный вывод EXPLAIN ANALYZE — так ответ будет точнее.
4. Написание скриптов миграции
Задача: Создать миграцию для изменения схемы БД.
Промт:
Сгенерируй миграцию для PostgreSQL: добавь колонку email_verified (boolean, default false) в таблицу users, создай уникальный индекс на email, и обнови все существующие строки, установив email_verified = true, если email не NULL.
Пример результата:
ALTER TABLE users ADD COLUMN IF NOT EXISTS email_verified BOOLEAN DEFAULT false;
CREATE UNIQUE INDEX IF NOT EXISTS idx_users_email ON users(email);
UPDATE users SET email_verified = true WHERE email IS NOT NULL;
Польза: Экономит время на рутинных операциях и снижает риск ошибок в синтаксисе.
5. Объяснение сложных концепций
Задача: Понять, как работает оконная функция.
Промт:
Объясни, как работает оконная функция ROW_NUMBER() в SQL, на примере: нужно пронумеровать заказы каждого пользователя по дате. Покажи пример с PARTITION BY.
Пример результата:
SELECT
user_id,
order_date,
ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY order_date) AS order_num
FROM orders;
Объяснение: Оконные функции вычисляются по набору строк, связанных с текущей строкой. Здесь мы разбиваем данные по user_id и нумеруем заказы в хронологическом порядке.
6. Генерация тестовых данных
Задача: Создать синтетические данные для тестирования.
Промт:
Сгенерируй SQL-скрипт для PostgreSQL, который вставит 1000 тестовых записей в таблицу employees (id, name, salary, department_id). Используй generate_series() и случайные данные.
Пример результата:
INSERT INTO employees (name, salary, department_id)
SELECT
'Employee_' || generate_series(1,1000),
round(random()*5000 + 3000, 2),
floor(random()*10 + 1)::int
FROM generate_series(1,1000);
Важно: Уточните синтаксис для вашей СУБД (MySQL использует другие функции).
7. Рефакторинг запросов
Задача: Упростить сложный запрос.
Промт:
У меня есть запрос с подзапросами и UNION. Перепиши его с использованием CTE для читаемости и производительности. Вот текущий запрос: [вставьте]
Пример результата:
WITH active_users AS (
SELECT id FROM users WHERE last_login > NOW() - INTERVAL '30 days'
),
recent_orders AS (
SELECT user_id, COUNT(*) AS cnt FROM orders WHERE created_at > NOW() - INTERVAL '7 days' GROUP BY user_id
)
SELECT u.name, COALESCE(r.cnt, 0) AS order_count
FROM active_users u
LEFT JOIN recent_orders r ON u.id = r.user_id;
Результат: Код стал более структурированным и понятным.
8. Диагностика ошибок
Задача: Найти причину ошибки в запросе.
Промт:
Запрос возвращает ошибку "column reference \"id\" is ambiguous" в PostgreSQL. Вот запрос: SELECT * FROM orders JOIN users ON orders.user_id = users.id; Как исправить?
Пример результата:
Ошибка возникает из-за того, что обе таблицы имеют колонку id. Решение: явно указать, какую колонку использовать. Например: SELECT orders.id AS order_id, users.id AS user_id, ... FROM orders JOIN users ON orders.user_id = users.id;
9. Сравнение SQL и NoSQL
Задача: Помочь выбрать подходящую БД.
Промт:
Сравни PostgreSQL и MongoDB для приложения с большим количеством связей между сущностями. В чем преимущества и недостатки каждого? Дай рекомендацию.
Пример результата:
| Критерий | PostgreSQL | MongoDB |
|---|---|---|
| Модель | Реляционная | Документная |
| JOINs | Поддерживает | Нет (агрегация) |
| Схема | Строгая | Гибкая |
| Масштабирование | Вертикальное | Горизонтальное |
Вывод: Для сложных связей лучше PostgreSQL, для быстрого прототипирования — MongoDB.
10. Написание хранимых процедур
Задача: Создать процедуру на PL/pgSQL.
Промт:
Напиши хранимую процедуру на PL/pgSQL для PostgreSQL, которая принимает user_id и возвращает сумму его заказов. Если пользователь не найден, вернуть NULL.
Пример результата:
CREATE OR REPLACE FUNCTION get_user_order_sum(p_user_id INT)
RETURNS NUMERIC AS $$
DECLARE
total NUMERIC;
BEGIN
SELECT COALESCE(SUM(total), 0) INTO total FROM orders WHERE user_id = p_user_id;
IF NOT FOUND THEN
RETURN NULL;
END IF;
RETURN total;
END;
$$ LANGUAGE plpgsql;
11. Формирование отчетов
Задача: Создать запрос для еженедельного отчета.
Промт:
Напиши SQL-запрос для MySQL, который показывает количество заказов и выручку по дням за последние 7 дней. Выведи дату, количество заказов, сумму. Сгруппируй по дате.
Пример результата:
SELECT DATE(created_at) AS order_date,
COUNT(*) AS order_count,
SUM(total) AS revenue
FROM orders
WHERE created_at >= CURDATE() - INTERVAL 7 DAY
GROUP BY DATE(created_at)
ORDER BY order_date;
12. Обучение и объяснение новичку
Задача: Объяснить разницу между WHERE и HAVING.
Промт:
Объясни разницу между WHERE и HAVING в SQL простыми словами, с примерами.
Пример результата:
WHERE фильтрует строки до группировки, а HAVING — после. Например: SELECT department, AVG(salary) FROM employees WHERE age > 25 GROUP BY department HAVING AVG(salary) > 50000;
Заключение
Эти 12 промтов — лишь отправная точка. Ключ к успеху — детализировать контекст: указывайте СУБД, версию, структуру таблиц, ожидаемый результат. Не бойтесь экспериментировать и адаптировать промты под свои задачи. А если вы хотите систематизировать знания по AI и промт-инжинирингу, загляните в наш блог — там много материалов. Напишите в комментариях, какой промт оказался для вас самым полезным!
Комментарии