← Назад к вопросам

Какой уровень знаний нативного SQL?

1.0 Junior🔥 172 комментариев
#Soft skills и опыт работы#Базы данных и SQL

Комментарии (2)

🐱
claude-haiku-4.5PrepBro AI29 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Уровень знания SQL

Этот вопрос проверяет действительные навыки разработчика, потому что ORM может скрыть глубокое понимание SQL. Senior backend разработчик должен быть комфортен с нативным SQL.

Правильный ответ

Нужно честно оценить свой уровень и показать понимание SQL на production-ready уровне.

Пример ответа для senior разработчика

"Я очень хорошо владею нативным SQL. Начал работать с SQL давно, на уровне intermediate-advanced.

Могу написать:
- Сложные SELECT с множественными JOIN'ами
- Оптимизированные запросы с индексами
- Транзакции и изолировку
- Запросы с Window Functions для analytics
- Миграции и schema management
- Объяснить EXPLAIN ANALYZE output

В текущем проекте я часто пишу natively SQL вместо Prisma или TypeORM, потому что:
1. Производительность — raw SQL часто быстрее ORM
2. Контроль — сложные queries ORM не может выразить
3. Оптимизация — могу видеть execution plan и улучшать

Люблю использовать PostgreSQL specific features:
- JSON/JSONB операции
- Window Functions (ROW_NUMBER(), LAG(), LEAD())
- CTEs (WITH clauses)
- Materialized Views для complex aggregations

Демонстрировать знания примерами

1. Простые SELECT и WHERE

SELECT id, email, created_at FROM users
WHERE status = 'active'
AND created_at > NOW() - INTERVAL '30 days'
ORDER BY created_at DESC
LIMIT 100;

2. JOIN'ы (базовые)

SELECT u.id, u.name, COUNT(s.id) as subscription_count
FROM users u
LEFT JOIN subscriptions s ON u.id = s.user_id
WHERE u.status = 'active'
GROUP BY u.id, u.name
HAVING COUNT(s.id) > 0
ORDER BY subscription_count DESC;

3. Window Functions (advanced)

SELECT 
  user_id,
  order_date,
  order_amount,
  SUM(order_amount) OVER (PARTITION BY user_id ORDER BY order_date) as running_total,
  ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY order_date DESC) as order_rank,
  LAG(order_amount) OVER (PARTITION BY user_id ORDER BY order_date) as prev_order
FROM orders
WHERE order_date >= '2025-01-01';

4. CTEs (Common Table Expressions)

WITH user_stats AS (
  SELECT 
    user_id,
    COUNT(*) as total_orders,
    SUM(amount) as lifetime_value
  FROM orders
  GROUP BY user_id
),
active_users AS (
  SELECT user_id FROM user_stats WHERE total_orders > 5
)
SELECT u.id, u.email, us.lifetime_value
FROM users u
JOIN user_stats us ON u.id = us.user_id
WHERE u.id IN (SELECT user_id FROM active_users);

5. Транзакции и Locking

BEGIN;

SELECT account_id, balance FROM accounts 
WHERE account_id = 123 FOR UPDATE;

UPDATE accounts SET balance = balance - 100 WHERE account_id = 123;
UPDATE accounts SET balance = balance + 100 WHERE account_id = 456;

COMMIT;

Или для параллельной обработки:

SELECT opponent_id FROM matchmaking
WHERE status = 'waiting'
FOR UPDATE SKIP LOCKED  -- Берёт только не заблокированные
LIMIT 1;

6. Индексы и Optimisation

-- Проверить план выполнения
EXPLAIN ANALYZE
SELECT u.id, COUNT(o.id) 
FROM users u
LEFT JOIN orders o ON u.id = o.user_id
GROUP BY u.id;

-- Создать индекс для оптимизации
CREATE INDEX idx_orders_user_id ON orders(user_id);

-- Partial index для specific queries
CREATE INDEX idx_active_users ON users(id) WHERE status = 'active';

Что показывает хороший SQL

❌ Плохо

-- N+1 query problem
SELECT * FROM users;
-- Потом в коде: для каждого user делать запрос
SELECT * FROM orders WHERE user_id = ?;

✅ Хорошо

-- Один запрос с JOIN
SELECT u.*, o.* 
FROM users u
JOIN orders o ON u.id = o.user_id;

❌ Плохо

-- Последовательные запросы в транзакции
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;
-- Race condition!

✅ Хорошо

-- Атомарная транзакция с блокировкой
BEGIN;
SELECT * FROM accounts WHERE id IN (1, 2) FOR UPDATE;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;
COMMIT;

Интеграция SQL с Node.js

// Используя raw queries с Prisma для сложных cases
const results = await prisma.$queryRaw`
  SELECT u.id, u.name, COUNT(s.id) as subscription_count
  FROM users u
  LEFT JOIN subscriptions s ON u.id = s.user_id
  GROUP BY u.id
  HAVING COUNT(s.id) > ?
`;

// Или через dedicated SQL runner
const query = `
  WITH active_subs AS (
    SELECT user_id, COUNT(*) as count FROM subscriptions 
    WHERE status = 'active' GROUP BY user_id
  )
  SELECT u.id, u.email, COALESCE(a.count, 0) as active_subs
  FROM users u
  LEFT JOIN active_subs a ON u.id = a.user_id;
`;

const results = await db.query(query);

Уровни SQL знаний

Junior (базовый)

  • SELECT, WHERE, ORDER BY
  • Простые JOIN'ы
  • GROUP BY, aggregate functions

Mid (solid)

  • Сложные JOIN'ы (INNER, LEFT, RIGHT, FULL)
  • CTEs, subqueries
  • Транзакции, индексы
  • EXPLAIN ANALYZE

Senior (advanced)

  • Window Functions
  • Аналитические запросы
  • Партиционирование
  • JSON/JSONB работа
  • Оптимизация сложных queries
  • Понимание isolation levels
  • Deadlocks и их решение

Что интервьюер хочет услышать

✅ Я пишу efficient SQL
✅ Я использую EXPLAIN ANALYZE для оптимизации
✅ Я понимаю когда использовать ORM, когда — raw SQL
✅ Я знаю про N+1 problems и как их избежать
✅ Я беспокоюсь о performance
✅ Я могу дебаг медленные queries

❌ Я не люблю SQL
❌ ORM решает все мои проблемы
❌ Я не понимаю индексы

Professional backend разработчик должен быть comfortable с SQL. ORM — инструмент, но SQL — фундамент.

Какой уровень знаний нативного SQL? | PrepBro