SQL-запрос для поиска неоцифрованных видеозаписей на кассетах

    В этой статье разберём, как написать корректный SQL-запрос, чтобы найти все видеозаписи, которые не были оцифрованы (то есть не имеют связанного файла). Исходная задача - есть база видеоархива с четырьмя таблицами: T_video (видеозаписи), T_nositel (носители: кассеты или файлы), T_type (типы носителей) и связующая таблица T_VN. Необходимо вывести только те записи, которые хранятся на кассетах, но не имеют цифровой копии (файла).

    Структура базы данных видеоархива

    Для понимания логики запроса важно знать схему таблиц:

    • T_video - содержит информацию о видеозаписях (idVideo, nameVideo).
    • T_nositel - носители (idNositel, nameNositel, typeNositel).
    • T_type - типы носителей (idType, nameType). Например, id=1 - кассета, id=3 - файл.
    • T_VN - связь между видео и носителями (idV, idN). Одна запись может быть на нескольких носителях.

    Проблема исходного решения на VBA

    Исходный код использовал функцию verifyType на VBA, которая проверяла, есть ли у видео носитель с типом 3 (файл). Если нет - запись считалась неоцифрованной. Это работало, но такой подход медленный, неудобный и привязан к Access. Гораздо лучше переписать всё на чистый SQL.

    Как составить SQL-запрос для поиска неоцифрованных записей

    Чтобы найти видеозаписи, у которых нет файла (typeNositel = 3), используйте оператор NOT EXISTS или LEFT JOIN с проверкой на NULL. Ниже приведён оптимальный вариант.

    SQL-запрос с NOT EXISTS (рекомендуется)

    SELECT v.nameVideo, n.nameNositel, t.nameType
    FROM T_video v
    INNER JOIN T_VN vn ON v.idVideo = vn.idV
    INNER JOIN T_nositel n ON vn.idN = n.idNositel
    INNER JOIN T_type t ON n.typeNositel = t.idType
    WHERE NOT EXISTS (
        SELECT 1
        FROM T_VN vn2
        INNER JOIN T_nositel n2 ON vn2.idN = n2.idNositel
        WHERE vn2.idV = v.idVideo AND n2.typeNositel = 3
    );

    Этот запрос выводит все видеозаписи вместе с их кассетами, но только те, для которых не существует ни одной записи в T_VN с типом носителя «файл» (typeNositel = 3).

    SQL-запрос с LEFT JOIN и проверкой на NULL

    SELECT v.nameVideo, n.nameNositel, t.nameType
    FROM T_video v
    INNER JOIN T_VN vn ON v.idVideo = vn.idV
    INNER JOIN T_nositel n ON vn.idN = n.idNositel
    INNER JOIN T_type t ON n.typeNositel = t.idType
    LEFT JOIN (
        SELECT DISTINCT vn2.idV
        FROM T_VN vn2
        INNER JOIN T_nositel n2 ON vn2.idN = n2.idNositel
        WHERE n2.typeNositel = 3
    ) AS file_video ON v.idVideo = file_video.idV
    WHERE file_video.idV IS NULL;

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

    Объяснение логики

    Мы присоединяем все связанные носители к видеозаписям, а затем отфильтровываем те, у которых нет связи с файлом. Если у видео есть хотя бы один файл, оно не попадает в результат. Таким образом, выводятся только записи, хранящиеся исключительно на кассетах (или других нецифровых носителях).

    Что делать, если нужно вывести все записи без файлов (в том числе без носителей)

    Если в базе могут быть видеозаписи, у которых вообще нет носителей (например, ещё не назначен), и вы хотите их тоже включить в выборку, замените INNER JOIN на LEFT JOIN для таблицы T_VN. Но по условию задачи, кажется, что каждая запись уже имеет хотя бы один носитель.

    Заключение

    Переход с VBA-функции на чистый SQL упрощает сопровождение и ускоряет выполнение запроса. Используйте NOT EXISTS или LEFT JOIN с IS NULL - оба способа корректно находят неоцифрованные видеозаписи. Теперь вы можете легко адаптировать этот запрос под свою базу данных.

    Часто задаваемые вопросы