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

Какие простые SQL-запросы использовал

1.8 Middle🔥 201 комментариев
#Основы Java

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

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

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

Простые SQL-запросы в повседневной работе Java Developer

В своей практике я регулярно использую набор простых, но эффективных SQL-запросов. Расскажу о самых полезных из них и когда их применяю.

1. Базовый SELECT с WHERE

Использование: Поиск пользователя по email

SELECT id, email, name, status, created_at
FROM users
WHERE email = 'user@example.com'
LIMIT 1;

В Java (JPA):

@Repository
public interface UserRepository extends JpaRepository<User, Long> {
    Optional<User> findByEmail(String email);
}

2. SELECT с несколькими условиями

Использование: Поиск активных заказов за период

SELECT id, user_id, total_amount, status, created_at
FROM orders
WHERE status = 'COMPLETED'
  AND created_at BETWEEN '2023-01-01' AND '2023-12-31'
  AND total_amount > 1000
ORDER BY created_at DESC
LIMIT 100;

В Java:

@Query("""
    SELECT o FROM Order o
    WHERE o.status = 'COMPLETED'
      AND o.createdAt BETWEEN :startDate AND :endDate
      AND o.totalAmount > :minAmount
    ORDER BY o.createdAt DESC
""")
List<Order> findCompletedOrdersByDateRange(
    @Param("startDate") LocalDate start,
    @Param("endDate") LocalDate end,
    @Param("minAmount") BigDecimal minAmount,
    Pageable pageable
);

3. INSERT простой записи

Использование: Создание нового пользователя

INSERT INTO users (email, name, status, created_at)
VALUES ('newuser@example.com', 'John Doe', 'ACTIVE', NOW());

В Java (Spring Data):

User user = User.builder()
    .email("newuser@example.com")
    .name("John Doe")
    .status(Status.ACTIVE)
    .createdAt(LocalDateTime.now(UTC))
    .build();

userRepository.save(user);

4. UPDATE условный

Использование: Активация пользователя после подтверждения email

UPDATE users
SET status = 'VERIFIED', verified_at = NOW()
WHERE id = 123
  AND status = 'PENDING';

В Java:

@Modifying
@Transactional
@Query("""
    UPDATE User u
    SET u.status = 'VERIFIED', u.verifiedAt = CURRENT_TIMESTAMP
    WHERE u.id = :userId AND u.status = 'PENDING'
""")
int verifyUser(@Param("userId") Long userId);

5. DELETE с условием

Использование: Удаление неактивных сессий

DELETE FROM sessions
WHERE user_id = 456
  AND last_accessed < NOW() - INTERVAL '7 days';

В Java:

@Modifying
@Transactional
@Query("""
    DELETE FROM Session s
    WHERE s.userId = :userId
      AND s.lastAccessed < CURRENT_TIMESTAMP - 7 DAY
""")
void deleteOldSessions(@Param("userId") Long userId);

6. COUNT для агрегации

Использование: Проверка количества активных пользователей

SELECT COUNT(*) as active_count
FROM users
WHERE status = 'ACTIVE'
  AND last_login > NOW() - INTERVAL '30 days';

В Java:

long activeUsersCount = userRepository.countByStatusAndLastLoginAfter(
    Status.ACTIVE,
    LocalDateTime.now(UTC).minusDays(30)
);

7. GROUP BY для статистики

Использование: Доход по категориям товаров

SELECT
    category,
    COUNT(*) as order_count,
    SUM(amount) as total_revenue,
    AVG(amount) as avg_order_value
FROM orders
WHERE status = 'COMPLETED'
  AND created_at > NOW() - INTERVAL '1 month'
GROUP BY category
ORDER BY total_revenue DESC;

В Java:

@Query("""
    SELECT new map(
        o.category as category,
        COUNT(o) as orderCount,
        SUM(o.amount) as totalRevenue,
        AVG(o.amount) as avgOrderValue
    )
    FROM Order o
    WHERE o.status = 'COMPLETED'
      AND o.createdAt > CURRENT_TIMESTAMP - 1 MONTH
    GROUP BY o.category
    ORDER BY SUM(o.amount) DESC
""")
List<Map<String, Object>> getRevenueByCategory();

8. JOIN для связанных данных

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

SELECT
    o.id,
    o.total_amount,
    u.email,
    u.name
FROM orders o
JOIN users u ON o.user_id = u.id
WHERE o.status = 'PENDING'
ORDER BY o.created_at DESC;

В Java (Spring Data):

@Query("""
    SELECT new OrderDTO(
        o.id,
        o.totalAmount,
        u.email,
        u.name
    )
    FROM Order o
    JOIN o.user u
    WHERE o.status = 'PENDING'
    ORDER BY o.createdAt DESC
""")
List<OrderDTO> findPendingOrdersWithUsers();

9. Pagination

Использование: Постраничный вывод списка

SELECT id, email, name
FROM users
WHERE status = 'ACTIVE'
ORDER BY created_at DESC
LIMIT 20 OFFSET 40; -- Страница 3, по 20 на странице

В Java:

Page<User> users = userRepository.findByStatus(
    Status.ACTIVE,
    PageRequest.of(2, 20, Sort.by("createdAt").descending())
);

10. DISTINCT для уникальных значений

Использование: Список стран, где есть пользователи

SELECT DISTINCT country
FROM users
WHERE status = 'ACTIVE'
ORDER BY country;

В Java:

@Query("""
    SELECT DISTINCT u.country
    FROM User u
    WHERE u.status = 'ACTIVE'
    ORDER BY u.country
""")
List<String> findDistinctCountries();

11. LEFT JOIN для опциональных данных

Использование: Пользователи с их профилями (если есть)

SELECT
    u.id,
    u.email,
    p.bio,
    p.avatar_url
FROM users u
LEFT JOIN profiles p ON u.id = p.user_id
WHERE u.status = 'ACTIVE';

В Java:

@Query("""
    SELECT new UserProfileDTO(
        u.id,
        u.email,
        p.bio,
        p.avatarUrl
    )
    FROM User u
    LEFT JOIN u.profile p
    WHERE u.status = 'ACTIVE'
""")
List<UserProfileDTO> findUsersWithProfiles();

12. EXISTS для проверки наличия данных

Использование: Проверка, есть ли у пользователя заказы

SELECT id, email
FROM users
WHERE EXISTS (
    SELECT 1 FROM orders
    WHERE user_id = users.id
      AND status = 'COMPLETED'
);

В Java:

@Query("""
    SELECT u FROM User u
    WHERE EXISTS (
        SELECT 1 FROM Order o
        WHERE o.user = u
          AND o.status = 'COMPLETED'
    )
""")
List<User> findUsersWithCompletedOrders();

Золотые правила SQL в Java-разработке

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

-- Неправильно (SQL Injection!)
SELECT * FROM users WHERE email = '" + email + "';

-- Правильно
SELECT * FROM users WHERE email = ?;

2. Индексируйте часто используемые колонки

CREATE INDEX idx_users_email ON users(email);
CREATE INDEX idx_orders_status_date ON orders(status, created_at);

**3. Избегайте SELECT ***

-- Неправильно
SELECT * FROM orders;

-- Правильно
SELECT id, user_id, total_amount FROM orders;

4. Используйте EXPLAIN для анализа

EXPLAIN ANALYZE
SELECT * FROM orders WHERE status = 'PENDING';

Вывод

В повседневной работе Java developer используются в основном простые запросы. Spring Data/JPA скрывают большую часть SQL-синтаксиса, но понимание базовых операций критично для эффективной работы с БД. Всегда профилируйте медленные запросы и добавляйте индексы, где нужно.