SQL без боли: 15 промтов, которые превратят ваш код из «работает» в «летает»

Вы когда-нибудь тратили полдня на запрос, который в итоге выполнялся 15 секунд и падал на продe? Или писали 200 строк SQL, а потом понимали, что можно было обойтись пятью? Если да — эта подборка для вас. Я собрал 15 промтов, которые реально ускоряют работу с SQL: от написания сложных запросов до оптимизации PostgreSQL и аналитики в BigQuery. Каждый промт — это готовая инструкция, которую можно скопировать и адаптировать под свою задачу. Никакой воды — только практика.

Почему это важно? По данным исследования Stack Overflow за 2024 год, SQL остаётся вторым по популярности языком после JavaScript — его используют 51% разработчиков. Но при этом большинство из них не умеют эффективно оптимизировать запросы. А ведь плохой запрос — это не только медленный отчёт, но и лишние деньги на облачных вычислениях (в BigQuery вы платите за каждый сканированный байт).

Я разбил промты на три блока: для новичков (написание запросов), для продвинутых (оптимизация) и для аналитиков (BigQuery). В каждом — пример, который можно запустить прямо сейчас. Поехали.

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

1. Генератор базового SELECT с JOIN

Когда использовать: нужно быстро получить выборку из двух-трёх таблиц, но не хочется вспоминать синтаксис JOIN.

Промт: «Напиши SQL-запрос для PostgreSQL, который выбирает все заказы из таблицы orders с полями id, customer_id, order_date, total_amount. Присоедини таблицу customers по полю customer_id, чтобы вывести имя и email клиента. Отсортируй по дате заказа по убыванию. Используй INNER JOIN, не забудь про алиасы.»

Пример использования:

SELECT o.id, o.order_date, o.total_amount, c.name, c.email
FROM orders o
INNER JOIN customers c ON o.customer_id = c.id
ORDER BY o.order_date DESC;

Почему это работает: Промт задаёт структуру, и модель генерирует корректный синтаксис. Вы экономите время на вспоминании деталей.

2. Трансформация словесного описания в SQL-код

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

Промт: «Преобразуй следующее описание в SQL-запрос для BigQuery: "Показать за последние 30 дней количество уникальных пользователей по дням, которые совершили хотя бы одну покупку. Включить только тех, у кого сумма покупок больше 1000 рублей. Результат отсортировать по дате." Учти, что таблица называется purchases с полями user_id, purchase_date, amount

Пример использования:

SELECT DATE(purchase_date) AS purchase_day, COUNT(DISTINCT user_id) AS unique_users
FROM `project.dataset.purchases`
WHERE purchase_date >= DATE_SUB(CURRENT_DATE(), INTERVAL 30 DAY)
  AND amount > 1000
GROUP BY purchase_day
ORDER BY purchase_day;

Совет: чем точнее опишете поля и условия, тем лучше результат.

3. Помощь с агрегацией и GROUP BY

Когда использовать: нужно посчитать сумму, среднее, количество по группам.

Промт: «Составь SQL-запрос для PostgreSQL, который по таблице sales (поля: sale_date, product_id, region, revenue) выводит сумму выручки (revenue) и количество продаж для каждого продукта в каждом регионе за последний квартал. Отфильтруй только те группы, где сумма выручки больше 50000. Используй GROUP BY, HAVING и функцию DATE_TRUNC для группировки по месяцам.»

Пример использования:

SELECT product_id, region, DATE_TRUNC('month', sale_date) AS month, SUM(revenue) AS total_revenue, COUNT(*) AS sales_count
FROM sales
WHERE sale_date >= CURRENT_DATE - INTERVAL '3 months'
GROUP BY product_id, region, month
HAVING SUM(revenue) > 50000
ORDER BY total_revenue DESC;

4. Исправление ошибок в SQL-коде

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

Промт: «Вот SQL-запрос для PostgreSQL, который возвращает ошибку: "SELECT * FROM orders WHERE order_date BETWEEN '2024-01-01' AND '2024-12-31' AND status = 'shipped' GROUP BY customer_id". Ошибка: "column orders.order_date must appear in the GROUP BY clause or be used in an aggregate function". Объясни, в чём проблема, и исправь запрос так, чтобы он выводил количество заказов по каждому клиенту за 2024 год.»

Исправленный код:

SELECT customer_id, COUNT(*) AS order_count
FROM orders
WHERE order_date BETWEEN '2024-01-01' AND '2024-12-31'
  AND status = 'shipped'
GROUP BY customer_id;

Почему это полезно: модель объясняет и исправляет, вы учитесь на своих ошибках.

Промты для оптимизации PostgreSQL (уровень: продвинутый)

5. Анализ плана выполнения запроса

Когда использовать: запрос работает медленно, нужно понять, почему.

Промт: «Вот EXPLAIN ANALYZE для PostgreSQL для запроса, который выбирает заказы за последний месяц с присоединением клиентов и товаров. Проанализируй план, найди узкие места (например, Seq Scan на больших таблицах, высокую стоимость, количество строк) и предложи конкретные меры по оптимизации: какие индексы создать, как переписать запрос. Приведи примеры кода создания индексов.»

Пример плана (упрощённо):

Hash Join  (cost=450.00..1450.00 rows=5000 width=100)
  -> Seq Scan on orders  (cost=0.00..1000.00 rows=50000 width=50)
  -> Hash  (cost=300.00..300.00 rows=10000 width=50)
        -> Seq Scan on customers  (cost=0.00..200.00 rows=10000 width=50)

Ответ модели: Seq Scan на orders — главная проблема. Создайте индекс:

CREATE INDEX idx_orders_order_date ON orders(order_date);
CREATE INDEX idx_orders_customer_id ON orders(customer_id);

6. Оптимизация запроса с подзапросами

Когда использовать: запрос с подзапросами работает медленно, можно переписать через JOIN или CTE.

Промт: «У нас есть запрос в PostgreSQL, который находит клиентов с суммой заказов больше среднего. Вот код: SELECT customer_id FROM orders GROUP BY customer_id HAVING SUM(amount) > (SELECT AVG(total) FROM (SELECT customer_id, SUM(amount) AS total FROM orders GROUP BY customer_id) sub). Запрос выполняется 10 секунд на 1 млн заказов. Предложи оптимизированную версию с использованием CTE и оконных функций, если это ускорит выполнение. Объясни, почему твой вариант лучше.»

Оптимизированный вариант:

WITH customer_totals AS (
  SELECT customer_id, SUM(amount) AS total
  FROM orders
  GROUP BY customer_id
),
avg_total AS (
  SELECT AVG(total) AS avg FROM customer_totals
)
SELECT customer_id
FROM customer_totals, avg_total
WHERE total > avg_total.avg;

7. Подбор индексов для конкретной таблицы

Когда использовать: нужно ускорить запросы, но не знаете, какие индексы создавать.

Промт: «В PostgreSQL есть таблица events с полями: id, user_id, event_type, created_at, payload (jsonb). Частые запросы: 1) SELECT * FROM events WHERE user_id = X AND created_at > Y; 2) SELECT event_type, COUNT(*) FROM events WHERE created_at BETWEEN A AND B GROUP BY event_type; 3) SELECT * FROM events WHERE payload->>'source' = 'web'. Предложи оптимальный набор индексов для этих запросов, учитывая размер таблицы (10 млн строк). Укажи типы индексов (B-tree, GIN и т.д.) и приведи SQL для создания.»

Ответ модели:

CREATE INDEX idx_events_user_created ON events(user_id, created_at);
CREATE INDEX idx_events_created_type ON events(created_at, event_type);
CREATE INDEX idx_events_payload_source ON events USING GIN ((payload->'source'));

8. Рефакторинг медленного запроса с OR

Когда использовать: запрос с OR не использует индексы, работает медленно.

Промт: «В PostgreSQL запрос SELECT * FROM products WHERE category = 'electronics' OR price < 100 выполняется очень медленно (Seq Scan). Перепиши его так, чтобы использовались индексы. Предложи вариант с UNION ALL и объясни, почему он может быть быстрее. Учти, что на таблице 5 млн строк, индексы на category и price уже есть.»

Переписанный запрос:

SELECT * FROM products WHERE category = 'electronics'
UNION ALL
SELECT * FROM products WHERE price < 100 AND category <> 'electronics';

9. Оптимизация запроса с большим количеством JOIN

Когда использовать: запрос соединяет 5+ таблиц и работает невыносимо долго.

Промт: «У нас есть запрос в PostgreSQL с 6 JOIN, который выполняется 30 секунд. Вот упрощённая структура: SELECT ... FROM orders o JOIN customers c ON ... JOIN order_items oi ON ... JOIN products p ON ... JOIN categories cat ON ... JOIN payments pay ON ... WHERE o.order_date > '2024-01-01'. Предложи стратегию оптимизации: что проверить в первую очередь (индексы, типы соединений), как переписать запрос (например, уменьшить количество JOIN, использовать агрегацию до соединения). Дай конкретные рекомендации и пример кода с предварительной агрегацией.»

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

WITH order_totals AS (
  SELECT order_id, SUM(quantity * price) AS total
  FROM order_items
  GROUP BY order_id
)
SELECT o.id, c.name, ot.total
FROM orders o
JOIN customers c ON o.customer_id = c.id
JOIN order_totals ot ON o.id = ot.order_id
WHERE o.order_date > '2024-01-01';

Промты для аналитики в BigQuery (уровень: аналитик)

10. Генерация отчёта по ежедневной выручке

Когда использовать: нужно быстро получить отчёт по продажам за период.

Промт: «Напиши запрос для BigQuery, который считает ежедневную выручку и количество заказов за последние 30 дней из таблицы sales с полями order_id, order_date, amount. Результат должен содержать дату, количество заказов и общую сумму, отсортированный по дате. Учти, что order_date — поле TIMESTAMP, а выручку считаем по amount (FLOAT64). Используй стандартный SQL BigQuery.»

Пример запроса:

SELECT 
  DATE(order_date) AS sale_day,
  COUNT(DISTINCT order_id) AS order_count,
  SUM(amount) AS total_revenue
FROM `project.dataset.sales`
WHERE order_date >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 30 DAY)
GROUP BY sale_day
ORDER BY sale_day;

11. Анализ пользовательского поведения с помощью оконных функций

Когда использовать: нужно посчитать retention, конверсию или скользящее среднее.

Промт: «Для BigQuery напиши запрос, который считает retention rate пользователей по дням после первой покупки. Есть таблица purchases с полями user_id, purchase_date. Определи дату первой покупки для каждого пользователя, затем для каждого дня после первой покупки (0, 1, 7, 30) посчитай, сколько пользователей совершили покупку в этот день. Используй оконные функции и CTE.»

Пример запроса:

WITH first_purchase AS (
  SELECT user_id, MIN(purchase_date) AS first_date
  FROM `project.dataset.purchases`
  GROUP BY user_id
),
daily_activity AS (
  SELECT user_id, purchase_date,
         DATE_DIFF(purchase_date, first_date, DAY) AS day_diff
  FROM `project.dataset.purchases` p
  JOIN first_purchase f USING(user_id)
)
SELECT day_diff, COUNT(DISTINCT user_id) AS retained_users
FROM daily_activity
WHERE day_diff IN (0, 1, 7, 30)
GROUP BY day_diff
ORDER BY day_diff;

12. Оптимизация запросов BigQuery: избегаем SELECT *

Когда использовать: запрос сканирует много данных, а нужно только несколько полей.

Промт: «В BigQuery запрос SELECT * FROM project.dataset.logs WHERE user_id = 123 сканирует 10 ГБ данных, а нужно только 3 поля. Перепиши запрос так, чтобы минимизировать количество сканируемых данных. Объясни, как использовать колоночное хранение BigQuery и какие поля лучше выбрать. Также предложи вариант с использованием кластеризации таблицы.»

Переписанный запрос:

SELECT event_type, created_at, user_id
FROM `project.dataset.logs`
WHERE user_id = 123;

Совет: используйте SELECT только с нужными колонками. Также можно создать кластеризованную таблицу по user_id:

CREATE TABLE `project.dataset.logs_clustered`
PARTITION BY DATE(created_at)
CLUSTER BY user_id
AS SELECT * FROM `project.dataset.logs`;

13. Создание отчёта по воронке продаж

Когда использовать: нужно построить конверсию по этапам воронки.

Промт: «Напиши запрос для BigQuery, который строит воронку продаж из таблицы events с полями user_id, event_name, event_date. Этапы: page_view, add_to_cart, checkout, purchase. Для каждого этапа посчитай количество уникальных пользователей и конверсию от предыдущего этапа. Используй функции агрегации и соединения. Результат — таблица с этапом, числом пользователей и конверсией.»

Пример запроса:

WITH funnel AS (
  SELECT 'page_view' AS stage, COUNT(DISTINCT user_id) AS users FROM `project.dataset.events` WHERE event_name = 'page_view'
  UNION ALL
  SELECT 'add_to_cart', COUNT(DISTINCT user_id) FROM `project.dataset.events` WHERE event_name = 'add_to_cart'
  UNION ALL
  SELECT 'checkout', COUNT(DISTINCT user_id) FROM `project.dataset.events` WHERE event_name = 'checkout'
  UNION ALL
  SELECT 'purchase', COUNT(DISTINCT user_id) FROM `project.dataset.events` WHERE event_name = 'purchase'
)
SELECT stage, users,
       LAG(users) OVER (ORDER BY CASE stage WHEN 'page_view' THEN 1 WHEN 'add_to_cart' THEN 2 WHEN 'checkout' THEN 3 WHEN 'purchase' THEN 4 END) AS prev_users,
       ROUND(users / LAG(users) OVER (ORDER BY CASE stage WHEN 'page_view' THEN 1 WHEN 'add_to_cart' THEN 2 WHEN 'checkout' THEN 3 WHEN 'purchase' THEN 4 END) * 100, 2) AS conversion_rate
FROM funnel
ORDER BY CASE stage WHEN 'page_view' THEN 1 WHEN 'add_to_cart' THEN 2 WHEN 'checkout' THEN 3 WHEN 'purchase' THEN 4 END;

14. Генерация дашборда с помощью SQL-запросов

Когда использовать: нужно подготовить данные для дашборда в Data Studio или Looker.

Промт: «Создай SQL-запрос для BigQuery, который выводит ключевые метрики для дашборда: общая выручка, количество заказов, средний чек, количество новых клиентов за каждый месяц за последние 6 месяцев. Таблицы: orders (order_id, customer_id, order_date, amount), customers (customer_id, signup_date). Результат должен быть готов для подключения к Looker Studio.»

Пример запроса:

SELECT 
  DATE_TRUNC(order_date, MONTH) AS month,
  SUM(amount) AS total_revenue,
  COUNT(DISTINCT order_id) AS order_count,
  ROUND(SUM(amount) / COUNT(DISTINCT order_id), 2) AS avg_check,
  COUNT(DISTINCT customers.customer_id) AS new_customers
FROM `project.dataset.orders`
LEFT JOIN `project.dataset.customers` ON orders.customer_id = customers.customer_id
WHERE order_date >= DATE_SUB(CURRENT_DATE(), INTERVAL 6 MONTH)
GROUP BY month
ORDER BY month;

15. Использование JSON-функций BigQuery для анализа логов

Когда использовать: данные хранятся в JSON, нужно извлечь поля.

Промт: «В BigQuery таблица logs содержит поле event_data типа JSON. Пример: {"action": "click", "page": "home", "duration": 12.5}. Напиши запрос, который извлекает action и duration из JSON, фильтрует по action = 'click' и считает среднюю длительность по страницам. Используй JSON_EXTRACT_SCALAR и JSON_EXTRACT или другие подходящие функции BigQuery.»

Пример запроса:

SELECT 
  JSON_EXTRACT_SCALAR(event_data, '$.page') AS page,
  AVG(CAST(JSON_EXTRACT_SCALAR(event_data, '$.duration') AS FLOAT64)) AS avg_duration
FROM `project.dataset.logs`
WHERE JSON_EXTRACT_SCALAR(event_data, '$.action') = 'click'
GROUP BY page
ORDER BY avg_duration DESC;

16. Оптимизация стоимости запросов BigQuery

Когда использовать: нужно сократить затраты на BigQuery.

Промт: «Мы тратим много денег на BigQuery из-за больших запросов. Как оптимизировать стоимость? Дай конкретные рекомендации и примеры SQL: использование партиционирования, кластеризации, материализованных представлений, ограничение SELECT *. Также объясни, как оценить стоимость запроса через сущности INFORMATION_SCHEMA.JOBS_BY_PROJECT.»

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

CREATE MATERIALIZED VIEW `project.dataset.daily_sales` AS
SELECT DATE(order_date) AS day, SUM(amount) AS total
FROM `project.dataset.orders`
GROUP BY day;

Как выбрать подходящий промт?

Если вы новичок — начните с первых четырёх. Они помогут освоить базовый синтаксис и избежать типичных ошибок. Если у вас уже есть рабочий код, но он тормозит — переходите к блоку оптимизации PostgreSQL. Аналитикам, работающим с большими данными, точно пригодятся промты для BigQuery — они экономят не только время, но и деньги.

Важно помнить: промты — это не волшебная палочка. Они работают лучше всего, когда вы понимаете, что делаете. Поэтому всегда проверяйте результат и разбирайтесь, почему запрос работает именно так.

Заключение

SQL — это навык, который окупается сторицей. С помощью этих промтов вы сможете быстрее писать запросы, оптимизировать медленные и получать инсайты из данных без лишней головной боли. Начните с простого — скопируйте промт, адаптируйте под свою базу и посмотрите, как изменится ваша продуктивность.

А если вы хотите ещё глубже прокачаться в работе с данными и AI-инструментами — загляните в другие статьи нашего блога. Там мы разбираем реальные кейсы и делимся практическими приёмами. Удачи в запросах!

← Все статьи

Комментарии

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