Найти тему
Илья Хохлов

Разбираем классические ошибки начинающих SQL-специалистов

При использовании подзапросов, довольно часто начинающие специалисты делают похожие ошибки. Возможно, и я в свое время их делал, но не могу припомнить наверняка. Я заметил, что если ученикам в ходе обучения рассказать про типичные ошибки при написании подзапросов, то внимательные ученики их после этого не делают! Чуть позже, мне в руки попал сборник вопросов на собеседованиях по SQL в США и в одном из вопросов был написан запрос с использованием подзапроса в котором специально была допущена одна из таких типичных ошибок. И я хочу рассказать тебе о ней, уважаемый читатель.

Запрос, данный ниже, должен показывать сотрудников (строчки из таблицы Persons) у которых нет автомобиля (нет записи с идентификатором сотрудника в таблице PersonCars), но, почему-то не выводит ни одной строчки. Как будто сотрудников без автомобиля нет.

-2

Присмотрись внимательно, увидишь ли ты ошибку?

Данный запрос не вернет ни одной строки и сейчас объясню почему! Ошибка заключается в том, что подзапрос должен был быть написан так, чтобы проверять подзапросом на отсутствие данных для каждой конкретной строки внешнего, то есть основного, запроса. Подзапрос написан для того, чтобы проверить отсутствие данных в таблице PersonCars для каждого сотрудника из таблицы Persons, который выводится в основном запросе. А сейчас наш подзапрос не связан с внешним запросом! Он проверяет на отсутствие следующих данных: что в таблице PersonCars отсутствуют строчки, в которых PersonID был бы равен самому себе!

Когда в подзапросе используется имя столбца без указания имени таблицы или алиаса (в нашем случае нужно было указать Person.PersonID), то СУБД сначала ищет столбец который имеется ввиду в рамках своего же SELECT, то есть подзапроса. Только если (под-)запрос не находит столбец в таблице (в подзапросе) из которой выбираются данные или среди таблиц, которые джоинятся (если такие есть), то пробует искать столбец с таким именем во внешнем (основном) запросе. В нашем случае PersonID есть в таблице PersonCars. Поэтому он сравнивается сам с собой. Конечно, для всех строчек PersonCars значение в столбце PersonID равно самому себе. Поэтому, какую бы строчку из таблицы Persons мы ни выводили, всегда существуют данные в таблице PersonCars где бы PersonID был бы равен сам себе. Поэтому NOT EXISTS для всех строчек таблицы Persons даст отрицательный результат и ни один сотрудник не выведется.

Вот исправленное решение:

-3

Если необходимо подзапрос связывать с внешним запросом, например, как в задаче выше, то крайне желательно, все же, в подзапросах, при написании имен столбцов, писать еще и имя таблицы этого столбца (или алиас).

И, конечно, важно стараться писать запросы внимательно :)

Буду рад, если подпишешься на мой канал или оставишь комментарий к моему посту!

Заходи на наш Youtube-канал и найдёшь много интересного и полезного про базы данных и язык SQL.

Если у тебя есть Telegram, подписывайся на наш канал. Несколько раз в неделю решаем вместе разные задачи по SQL, и еще помогаю не выпадать из темы айти. Делюсь полезной информацией и техническим-юмором:)

А здесь ты можешь пройти наш курс обучения языку SQL и получить мощные знания и умения! Всего за 27 уроков до уровня специалиста, имеющего трёхлетний стаж. Много практики в реальной базе данных! С нашей поддержкой и проверкой твоих самостоятельный задач! Записывайся, буду тебя ждать!