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

Будешь ли писать SQL-запросы при использовании команд

1.0 Junior🔥 11 комментариев
#Инструменты и DevOps

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

🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)

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

Будешь ли писать SQL-запросы при использовании ОRM (Object-Relational Mapping)

Этот вопрос уточняет, нужно ли фронтенд-разработчику знать SQL при работе с ОRM инструментами. Ответ зависит от контекста и типа работы, которую ты выполняешь.

Краткий ответ

Да, знание SQL полезно, но не обязательно для начинающих. ORM позволяет писать код без SQL, но понимание SQL помогает писать более эффективные запросы и отлаживать проблемы.

Что такое ORM

ORM (Object-Relational Mapping) — это инструмент, который преобразует объекты в коде в строки в базе данных и наоборот:

// Без ORM — пишешь SQL
const sql = "SELECT * FROM users WHERE age > 18";
const users = await db.query(sql);

// С ORM — пишешь на языке программирования
const users = await User.find({ where: { age: { $gt: 18 } } });
// или
const users = await db.query(User).where(u => u.age > 18).find();

Когда нужен SQL при работе с ORM

1. Сложные запросы

// ORM может быть неудобным для сложных запросов
const stats = await sequelize.query(`
  SELECT 
    users.name,
    COUNT(posts.id) as post_count,
    AVG(posts.likes) as avg_likes
  FROM users
  LEFT JOIN posts ON users.id = posts.user_id
  GROUP BY users.id
  HAVING COUNT(posts.id) > 5
  ORDER BY post_count DESC
`);

// То же самое на ORM может быть громоздким
const stats = await User.findAll({
  include: [{ model: Post, attributes: [] }],
  attributes: [
    "name",
    [sequelize.fn("COUNT", sequelize.col("posts.id")), "post_count"],
    [sequelize.fn("AVG", sequelize.col("posts.likes")), "avg_likes"]
  ],
  group: ["users.id"],
  having: sequelize.where(
    sequelize.fn("COUNT", sequelize.col("posts.id")),
    sequelize.Op.gt,
    5
  ),
  order: [["post_count", "DESC"]]
});

2. Оптимизация производительности

// Плохо: N+1 query problem
const users = await User.find();
for (const user of users) {
  // Для каждого пользователя отдельный запрос!
  const posts = await Post.find({ userId: user.id });
}

// Хорошо: один запрос с JOIN (нужно знать SQL)
const users = await User.find()
  .include(["posts"]) // Загружаем посты в одном запросе
  .exec();

// Или raw SQL, если ORM неудобен
const data = await sequelize.query(`
  SELECT users.*, posts.* 
  FROM users 
  LEFT JOIN posts ON users.id = posts.user_id
`);

3. Миграции БД

// Даже с ORM нужно понимать SQL структуру
// Миграция на Sequelize
module.exports = {
  up: async (queryInterface, Sequelize) => {
    await queryInterface.createTable("users", {
      id: {
        type: Sequelize.INTEGER,
        primaryKey: true,
        autoIncrement: true
      },
      name: Sequelize.STRING,
      email: {
        type: Sequelize.STRING,
        unique: true
      }
    });
  }
};

// А это в чистом SQL
CREATE TABLE users (
  id INTEGER PRIMARY KEY AUTO_INCREMENT,
  name VARCHAR(255),
  email VARCHAR(255) UNIQUE
);

ORM vs Raw SQL: Сравнение

Простой запрос

// ORM (удобнее)
const user = await User.findByPk(1);

// SQL (громоздче)
const [user] = await db.query("SELECT * FROM users WHERE id = 1");

Средний запрос

// ORM
const users = await User.findAll({
  where: { age: { $gte: 18, $lte: 30 } },
  include: ["profile"],
  limit: 10,
  offset: 0,
  order: [["createdAt", "DESC"]]
});

// SQL
const users = await db.query(`
  SELECT u.*, p.*
  FROM users u
  LEFT JOIN profiles p ON u.id = p.user_id
  WHERE u.age BETWEEN 18 AND 30
  ORDER BY u.created_at DESC
  LIMIT 10 OFFSET 0
`);

Сложный запрос

// ORM (очень громоздкий)
const result = await User.findAll({
  attributes: [
    "id",
    "name",
    [sequelize.fn("COUNT", sequelize.col("posts.id")), "totalPosts"],
    [sequelize.fn("MAX", sequelize.col("posts.likes")), "maxLikes"]
  ],
  include: [{ model: Post, attributes: [] }],
  group: ["users.id"],
  having: sequelize.where(
    sequelize.fn("COUNT", sequelize.col("posts.id")),
    sequelize.Op.gt,
    3
  ),
  subQuery: false,
  raw: true
});

// SQL (более читаемый)
const result = await db.query(`
  SELECT 
    u.id,
    u.name,
    COUNT(p.id) as totalPosts,
    MAX(p.likes) as maxLikes
  FROM users u
  LEFT JOIN posts p ON u.id = p.user_id
  GROUP BY u.id
  HAVING COUNT(p.id) > 3
`);

Популярные ORM/Query builders

// Sequelize (Node.js)
const user = await User.findOne({ where: { email: "user@example.com" } });

// TypeORM (TypeScript/Node.js)
const user = await userRepository.findOne({ where: { email: "user@example.com" } });

// Knex.js (Query builder, не полноценный ORM)
const user = await knex("users").where({ email: "user@example.com" }).first();

// Prisma (Modern ORM)
const user = await prisma.user.findUnique({ where: { email: "user@example.com" } });

// Django ORM (Python)
user = User.objects.get(email="user@example.com")

// Laravel Eloquent (PHP)
$user = User::where("email", "user@example.com")->first();

Мой опыт: когда я писал SQL

В работе фронтенд-разработчика я редко пишу SQL напрямую, потому что:

  1. API слой — бэкенд предоставляет готовые endpoints

    // Фронтенд
    const users = await fetch("/api/users?age=18&limit=10");
    
  2. ORM достаточно — для большинства случаев ORM удобнее

    const users = await User.find({ age: 18 }).limit(10);
    
  3. Когда нужен SQL — изредка для оптимизации

    // Только для сложных аналитик запросов
    const report = await db.query("SELECT ... GROUP BY ... HAVING ...");
    

Рекомендация

Как фронтенд-разработчик, я рекомендую:

  1. Учи основы SQL — SELECT, WHERE, JOIN, GROUP BY
  2. Выбери один ORM — Sequelize, TypeORM или Prisma
  3. Писать в ORM по-умолчанию — это быстрее
  4. Обращайся к SQL только когда необходимо — для оптимизации или очень сложных запросов
  5. Понимай, как ORM трансформирует в SQL — для отладки

Практический пример

// Мой подход в реальном проекте

// 1. Обычные операции — ORM
const user = await User.findById(userId);
await user.update({ lastLogin: new Date() });

// 2. Связанные данные — ORM с include
const user = await User.findById(userId)
  .include(["posts", "comments"]); // Eager loading

// 3. Сложные фильтры — ORM query builder
const activeUsers = await User.find()
  .where("lastLogin").gte(thirtyDaysAgo)
  .where("verified").equals(true)
  .select("name email lastLogin")
  .limit(100);

// 4. Аналитика — raw SQL
const stats = await db.query(`
  SELECT 
    DATE(created_at) as date,
    COUNT(*) as new_users,
    SUM(CASE WHEN verified THEN 1 ELSE 0 END) as verified
  FROM users
  GROUP BY DATE(created_at)
  ORDER BY date DESC
  LIMIT 30
`);

Заключение

Для фронтенд-разработчика SQL обычно не требуется, если ты работаешь с готовым API. Но понимание SQL поможет тебе:

  • Писать более эффективный ORM код
  • Отлаживать проблемы производительности
  • Общаться с бэкенд-разработчиками
  • Переходить на полноценную разработку бэкенда
Будешь ли писать SQL-запросы при использовании команд | PrepBro