Собесов

SQL: сколько студентов завершили хотя бы один курс

SQLАгрегация и DISTINCTЛёгкаяJunior

Условие

Есть три таблицы:

students (student_id TEXT, full_name, city, signup_date DATE).

enrollments (enroll_id, student_id, course, enroll_date, progress_pct INT (0–100), status TEXTcompleted / in_progress / cancelled, может быть NULL).

reviews (review_id, enroll_id, rating INT 1–5, review_date).

Напишите запрос, который выведет, сколько студентов завершили хотя бы один курс. Завершённым считается обучение со status = 'completed'.

PostgreSQL 15.5. Время — 1 секунда, память — 128 МБ.

Решение

Подход

Один студент мог завершить несколько курсов — нужен COUNT(DISTINCT student_id). Не нужны JOIN-ы — данные есть в enrollments.

Реализация

SELECT COUNT(DISTINCT student_id) AS students_completed
FROM enrollments
WHERE status = 'completed';

Альтернатива через подзапрос (читабельнее в больших запросах)

SELECT COUNT(*) AS students_completed
FROM (
    SELECT DISTINCT student_id
    FROM enrollments
    WHERE status = 'completed'
) t;

Сложность

O(n) на сканировании enrollments + сортировка/хеш для DISTINCT. На таблице с миллионами строк лучше иметь индекс по (status, student_id).

Подводные камни

  1. COUNT(student_id) без DISTINCT. Посчитает количество завершённых обучений, а не уникальных студентов. Если Иванов завершил 3 курса — будет +3 вместо +1.
  2. status = 'completed' против IS NOT NULL. Условие задачи — именно 'completed', а не «не отменён». Студент с in_progress не считается завершившим.
  3. status может быть NULL. WHERE status = 'completed' корректно отбрасывает NULL-ы (трёхзначная логика). Но если случайно сравнить status <> 'cancelled', NULL-ы тоже отвалятся (а вы могли их хотеть).
  4. Регистр статуса. PostgreSQL чувствителен к регистру: 'Completed''completed'. Если данные грязные — LOWER(status) = 'completed', но это блокирует индекс.

Эталонный ответ

SELECT COUNT(DISTINCT student_id)
FROM enrollments
WHERE status = 'completed';

Хочешь увидеть разбор?

Зарегистрируйся бесплатно — откроется развёрнутое решение этой задачи и ещё 4 на выбор.

Зарегистрироваться и увидеть разбор
Уже есть аккаунт? Войти