Нейросеть как DBA: 12 промтов для PostgreSQL, которые решают реальные задачи

Вы когда-нибудь писали SQL-запрос, который выполнялся так долго, что успевали сходить за кофе, а он всё ещё крутился? Или проектировали схему базы данных, а через месяц понимали, что нормализация пошла не туда? Если да — вы не одиноки. Многие разработчики и аналитики тратят часы на написание и оптимизацию запросов, хотя могли бы делегировать рутину нейросети. Я собрал 12 проверенных промтов, которые превратят ChatGPT или другую LLM в вашего персонального DBA и аналитика. Это не магия, а инженерия: каждый промт я тестировал на реальных задачах, и теперь делюсь с вами.

Почему промты для SQL — это не игрушки

Прежде чем перейти к подборке, давайте разберёмся, почему нейросети вообще могут писать SQL. Современные LLM обучались на огромном количестве кода, включая дампы GitHub и Stack Overflow. Они знают синтаксис PostgreSQL, типичные ошибки и паттерны. Но главное — они понимают контекст. Если вы опишете структуру таблиц и задачу, модель сгенерирует запрос, который часто работает с первого раза. Конечно, бывают ошибки, но с правильными промтами их можно свести к минимуму.

Официальная документация PostgreSQL (https://www.postgresql.org/docs/) — ваш лучший друг. Я рекомендую всегда сверять сгенерированный код с ней, особенно если речь идёт о сложных оконных функциях или работе с JSONB. Нейросеть может предложить синтаксис, который устарел или не подходит для вашей версии, поэтому проверка обязательна.

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

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

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

Промт:

У меня есть таблицы в PostgreSQL:
- users (id, name, email, created_at)
- orders (id, user_id, amount, status, created_at)
- order_items (id, order_id, product_id, quantity, price)
- products (id, name, category, price)

Напиши SQL-запрос, который выведет для каждого пользователя сумму его заказов за последние 30 дней. Включи только пользователей с суммой больше 1000. Отсортируй по сумме убыванию.

Результат:

SELECT 
    u.name,
    SUM(o.amount) AS total_amount
FROM 
    users u
JOIN 
    orders o ON u.id = o.user_id
WHERE 
    o.created_at >= NOW() - INTERVAL '30 days'
    AND o.status = 'completed'
GROUP BY 
    u.id, u.name
HAVING 
    SUM(o.amount) > 1000
ORDER BY 
    total_amount DESC;

Почему это работает: модель понимает, что нужно соединить таблицы, отфильтровать по дате и группировать. Обратите внимание на HAVING — это правильный способ фильтрации после агрегации. Если бы вы написали WHERE с суммой, получили бы ошибку.

2. Объяснение сложного запроса

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

Промт:

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

WITH ranked AS (
    SELECT 
        product_id,
        ROW_NUMBER() OVER (PARTITION BY category ORDER BY price DESC) AS rn
    FROM products
)
SELECT * FROM ranked WHERE rn <= 3;

Результат:

Модель объяснит, что это оконная функция ROW_NUMBER(), которая нумерует продукты внутри каждой категории по убыванию цены, а затем выбирает топ-3 самых дорогих продукта в каждой категории. Она также может добавить примечание, что ROW_NUMBER() присваивает уникальные номера, и если есть одинаковые цены, порядок будет произвольным. Если это критично, лучше использовать RANK() или DENSE_RANK().

3. Исправление ошибки в запросе

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

Промт:

У меня есть запрос, который вызывает ошибку в PostgreSQL:

SELECT name, COUNT(*) 
FROM users 
JOIN orders ON users.id = orders.user_id
WHERE created_at > '2025-01-01'
GROUP BY name;

Ошибка: column "users.created_at" must appear in the GROUP BY clause or be used in an aggregate function. Как исправить?

Результат:

Модель объяснит, что в WHERE нельзя использовать агрегаты и что колонка created_at должна быть либо в GROUP BY, либо в агрегатной функции. Правильный вариант:

SELECT 
    u.name,
    COUNT(*) AS order_count
FROM 
    users u
JOIN 
    orders o ON u.id = o.user_id
WHERE 
    o.created_at > '2025-01-01'
GROUP BY 
    u.id, u.name;

Также добавит совет: если нужно фильтровать по агрегату, используйте HAVING.

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

4. Оптимизация медленного запроса

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

Промт:

У меня есть запрос, который выполняется 15 секунд на таблице с миллионом строк. Вот он:

SELECT * 
FROM orders 
WHERE user_id IN (SELECT id FROM users WHERE created_at > '2025-01-01');

Как его оптимизировать? Дайте конкретные советы и перепишите запрос, если нужно.

Результат:

Модель может предложить использовать JOIN вместо подзапроса, добавить индексы на user_id и created_at, а также избегать SELECT *. Пример:

SELECT 
    o.*
FROM 
    orders o
JOIN 
    users u ON o.user_id = u.id
WHERE 
    u.created_at > '2025-01-01';

И добавит: для максимальной производительности создайте индекс: CREATE INDEX idx_users_created_at ON users(created_at); и CREATE INDEX idx_orders_user_id ON orders(user_id);. Также стоит проверить план выполнения через EXPLAIN ANALYZE.

5. Проектирование схемы базы данных

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

Промт:

Спроектируй схему базы данных для интернет-магазина. Нужны таблицы для пользователей, товаров, корзины и заказов. Учитывай, что товары могут иметь несколько категорий, а пользователи — несколько адресов доставки. Используй PostgreSQL. Покажи SQL-код создания таблиц с ограничениями и индексами.

Результат:

Модель предложит связи многие-ко-многим для товаров и категорий, отдельную таблицу адресов, а также продумает внешние ключи и индексы. Например:

CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    email VARCHAR(255) UNIQUE NOT NULL,
    password_hash TEXT NOT NULL,
    created_at TIMESTAMP DEFAULT NOW()
);

CREATE TABLE categories (
    id SERIAL PRIMARY KEY,
    name VARCHAR(100) NOT NULL
);

CREATE TABLE products (
    id SERIAL PRIMARY KEY,
    name VARCHAR(255) NOT NULL,
    price NUMERIC(10,2) NOT NULL CHECK (price >= 0),
    stock INT NOT NULL DEFAULT 0
);

CREATE TABLE product_categories (
    product_id INT REFERENCES products(id) ON DELETE CASCADE,
    category_id INT REFERENCES categories(id) ON DELETE CASCADE,
    PRIMARY KEY (product_id, category_id)
);

CREATE TABLE addresses (
    id SERIAL PRIMARY KEY,
    user_id INT REFERENCES users(id) ON DELETE CASCADE,
    street TEXT NOT NULL,
    city VARCHAR(100) NOT NULL,
    zip_code VARCHAR(20)
);

CREATE TABLE orders (
    id SERIAL PRIMARY KEY,
    user_id INT REFERENCES users(id),
    address_id INT REFERENCES addresses(id),
    status VARCHAR(20) DEFAULT 'pending',
    created_at TIMESTAMP DEFAULT NOW()
);

CREATE TABLE order_items (
    order_id INT REFERENCES orders(id) ON DELETE CASCADE,
    product_id INT REFERENCES products(id),
    quantity INT NOT NULL CHECK (quantity > 0),
    price NUMERIC(10,2) NOT NULL,
    PRIMARY KEY (order_id, product_id)
);

Это базовый, но рабочий вариант. Модель также может добавить триггер для обновления остатков.

6. Написание миграций

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

Промт:

В моей таблице products есть колонка price типа NUMERIC. Мне нужно переименовать её в unit_price, а также добавить колонку currency VARCHAR(3) со значением по умолчанию 'USD'. Напиши SQL-миграцию для PostgreSQL, которая сделает это безопасно, с учётом возможного наличия зависимостей.

Результат:

Модель предложит использовать ALTER TABLE с проверкой существования, чтобы избежать ошибок. Например:

BEGIN;

ALTER TABLE products 
    RENAME COLUMN price TO unit_price;

ALTER TABLE products 
    ADD COLUMN IF NOT EXISTS currency VARCHAR(3) DEFAULT 'USD';

COMMIT;

Она также посоветует обновить все зависимые представления или код приложения.

Экспертные промты: для аналитиков и не только

7. Создание отчёта с группировками

Задача: сгенерировать отчёт по продажам с разбивкой по месяцам и категориям.

Промт:

У меня есть таблицы: orders, order_items, products, categories. Напиши запрос, который покажет для каждого месяца (за 2025 год) общую выручку по каждой категории товаров. Включи месяцы, в которых не было продаж, с нулевой выручкой. Используй generate_series для заполнения пропусков.

Результат:

WITH months AS (
    SELECT generate_series('2025-01-01'::date, '2025-12-01'::date, '1 month') AS month_start
)
SELECT 
    to_char(m.month_start, 'YYYY-MM') AS month,
    c.name AS category,
    COALESCE(SUM(oi.quantity * oi.price), 0) AS revenue
FROM 
    months m
CROSS JOIN 
    categories c
LEFT JOIN 
    products p ON c.id = p.category_id
LEFT JOIN 
    order_items oi ON p.id = oi.product_id
LEFT JOIN 
    orders o ON oi.order_id = o.id AND date_trunc('month', o.created_at) = m.month_start AND o.status = 'completed'
GROUP BY 
    m.month_start, c.name
ORDER BY 
    month, category;

Здесь ключевая идея — generate_series и CROSS JOIN, чтобы получить все комбинации месяц-категория.

8. Анализ данных с помощью оконных функций

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

Промт:

Используя таблицу orders (id, user_id, amount, created_at), напиши запрос, который для каждого дня в 2025 году выводит:
- сумму заказов за день
- скользящее среднее за 7 дней (включая текущий)
- разницу между текущим днём и предыдущим

Отсортируй по дате.

Результат:

WITH daily AS (
    SELECT 
        created_at::date AS day,
        SUM(amount) AS amount
    FROM 
        orders
    WHERE 
        created_at >= '2025-01-01' AND created_at < '2026-01-01'
    GROUP BY 
        created_at::date
)
SELECT 
    day,
    amount,
    AVG(amount) OVER (ORDER BY day ROWS BETWEEN 6 PRECEDING AND CURRENT ROW) AS avg_7d,
    amount - LAG(amount) OVER (ORDER BY day) AS diff_prev
FROM 
    daily
ORDER BY 
    day;

Модель объяснит, что LAG обращается к предыдущей строке, а ROWS BETWEEN определяет рамки окна.

9. Поиск дубликатов и аномалий

Задача: найти дублирующиеся записи в таблице пользователей по email.

Промт:

В таблице users есть колонка email, но нет уникального ограничения. Найди все дубликаты email и выведи id всех пользователей с одинаковыми email.

Результат:

SELECT 
    email,
    array_agg(id) AS user_ids,
    COUNT(*) AS cnt
FROM 
    users
GROUP BY 
    email
HAVING 
    COUNT(*) > 1;

Модель также предложит вариант с оконной функцией, если нужно увидеть каждую строку отдельно, и посоветует добавить уникальный индекс после очистки.

10. Использование JSONB для гибких данных

Задача: работать с JSONB-полями, например, извлекать значения и фильтровать.

Промт:

У меня есть таблица events (id, user_id, payload JSONB). Напиши запрос, который выведет user_id и количество событий, где payload содержит ключ 'type' со значением 'click'. Также покажи, как извлечь значение 'page' из payload.

Результат:

SELECT 
    user_id,
    COUNT(*) AS click_count,
    payload->>'page' AS page
FROM 
    events
WHERE 
    payload->>'type' = 'click'
GROUP BY 
    user_id, payload->>'page';

Модель пояснит, что ->> возвращает текст, а -> возвращает JSONB. Для производительности стоит создать GIN-индекс: CREATE INDEX idx_events_payload ON events USING GIN(payload);.

11. Рекурсивные запросы для иерархий

Задача: обойти дерево категорий или структуру сотрудников.

Промт:

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

Результат:

WITH RECURSIVE subordinates AS (
    SELECT id, name, manager_id
    FROM employees
    WHERE id = 1
    UNION ALL
    SELECT e.id, e.name, e.manager_id
    FROM employees e
    JOIN subordinates s ON e.manager_id = s.id
)
SELECT * FROM subordinates;

Это классический пример WITH RECURSIVE, который часто используется в организационных структурах.

12. Сравнение производительности двух вариантов запроса

Задача: понять, какой запрос эффективнее.

Промт:

Сравни два запроса для получения количества заказов по каждому пользователю. Первый использует подзапрос, второй — JOIN. Какой из них будет быстрее и почему? Покажи, как проверить с помощью EXPLAIN ANALYZE.

Результат:

Модель объяснит, что современный планировщик PostgreSQL может переписать подзапрос в JOIN, но в некоторых случаях JOIN будет эффективнее, особенно при наличии индексов. Она предложит использовать EXPLAIN ANALYZE:

EXPLAIN ANALYZE SELECT u.id, (SELECT COUNT(*) FROM orders o WHERE o.user_id = u.id) FROM users u;
EXPLAIN ANALYZE SELECT u.id, COUNT(o.id) FROM users u LEFT JOIN orders o ON o.user_id = u.id GROUP BY u.id;

И посоветует сравнивать время выполнения и стоимость.

Как адаптировать промты под свою базу данных

Приведённые промты — это шаблоны. Чтобы получить максимальную пользу, адаптируйте их:

  • Указывайте реальные имена таблиц и колонок. Чем точнее описание, тем лучше результат.
  • Добавляйте контекст о версии PostgreSQL. Например, PostgreSQL 15.
  • Просите объяснить, если что-то непонятно. Вы можете задать уточняющие вопросы.
  • Всегда проверяйте сгенерированный код на тестовой базе. Никогда не запускайте непроверенный код на проде.

Вывод

Нейросети не заменят опытного DBA, но они могут снять с вас рутину и ускорить разработку. Используйте эти промты как отправную точку, адаптируйте под свои задачи и не забывайте проверять результат. Если вы хотите систематизировать знания и научиться применять ИИ в работе с базами данных, обратите внимание на наши курсы в блоге ASI Biont — там мы разбираем такие примеры на реальных кейсах. А теперь — идите и оптимизируйте свои запросы!

← Все статьи

Комментарии

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

DevOps с нуля: CI/CD, Docker, мониторинг за 30 дней — пошаговый план

18 июня 2026

The Community Champions Program: Как Zed.dev отмечает лучших участников сообщества

20 июня 2026

Освоение ИТ-права и комплаенса: почему этот курс на Asibiont.com — ваш ключ к навигации по GDPR, рискам ИИ и защите данных в 2026 году

29 июня 2026

Anthropic подписывает сделку на $10 млрд с AI-облачным стартапом Volta: что изменится для рынка и vibe coding

5 августа 2026

От ноутбука до продакшена: как курс ML in Production на asibiont.com трансформирует навыки MLOps

25 июня 2026

Безопасность на передовой: как Google DeepMind усиливает Frontier Safety Framework в 2026 году

21 июня 2026

Курс по Kotlin и разработке под Android 2026: Почему обучение с ИИ — ваш быстрый путь к карьере мобильного разработчика

12 июля 2026

Курс мобильной разработки 2026: создавайте приложения с Flutter, React Native и обучением на основе ИИ

13 июля 2026

Heresy в AI-разработке: как Vibe Coding переписывает правила игры в 2026 году

18 июля 2026