SQL для начинающих

Урок 3. Порядок AND и OR

При использовании в SELECT-запросах операторов OR и AND можно легко ошибиться в составлении логического выражения. И проблема таких ошибок в том, что запрос выполняется как будто ошибки нет, но данные выводятся неверные.

Если у вас мало опыта в написании таких SQL-запросов, то можно легко не заметить проблему. Давайте разберем несколько популярных ошибок.

Работать будем с таблицей team, которая содержит список разработчиков:

Таблица team
idfirst_namelast_namelanguagelevel
1ДмитрийВасильевpythonjunior
2ВалерийЮрьевphpmiddle
3АндрейУшаковpythonsenior
4ПетрКузубjavascriptjunior
5НатальяКузнецоваpythonmiddle
6РусланИсаковphpsenior
7СергейМедведевphpjunior
8АлексейБорисовpythonmiddle
9ВалерияМарковаjavasciptsenior

Каждый разработчик оценивается project-менеджером по двум критериям, после чего он отбирает программиста на тот или иной проект. Основные критерии — это уровень владения технологией: junior, middle или senior, и базовый язык программирования, на котором пишет разработчик.

Нам как менеджерам поступает заявка на разработку проекта и на основании этой заявки мы должны подобрать необходимых разработчиков.

Представьте, что сейчас нас интересуют только мидллы и сеньоры. Напишем SQL-запрос:

SELECT * FROM team WHERE level = 'middle' AND level = 'senior'

После выполнения запроса мы увидим пустую таблицу.

Результат выполнения — пустая таблица
idfirst_namelast_namelanguagelevel

И тут мы столкнулись с первой ошибкой. В нашем запросе база данных по очереди берет строку и проверяет находится ли в колонке level значение "middle" И значение "senior". Оператор AND — это условие одновременности. То есть исходя из нашего запроса в поле level должно находится одновременно и "middle", и "senior", что невозможно, так разработчик может быть только одного уровня.

Почему мы допустили такую ошибку? И дело в формулировках, когда я озвучивал задание, то сказал, что нас интересуют только мидлы И сеньоры. Это правильное выражение с точки зрения русского языка, но неверное с точки зрения логики. Чтобы получить верный результат надо чтобы поле level содержало ИЛИ "middle", ИЛИ "senior". Поэтому заменим AND на OR:

SELECT * FROM team WHERE level = 'middle' OR level = 'senior'

Теперь разработчики подобраны верно:

Получили всех middle и senior разработчиков
idfirst_namelast_namelanguagelevel
2ВалерийЮрьевphpmiddle
3АндрейУшаковpythonsenior
5НатальяКузнецоваpythonmiddle
6РусланИсаковphpsenior
8АлексейБорисовpythonmiddle
9ВалерияМарковаjavasciptsenior

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

Давайте рассмотрим другой случай. На этот раз нам нужно разработать бэкенд для сайта. И для этого нам нужны все Python и PHP разработчики. Напишем:

SELECT * FROM team 
WHERE basic_language = 'Python' OR basic_language = "PHP"

Обратите внимание, что нужны нам все Python И PHP разработчики, но пишем мы OR. После выполнения запроса мы получим такую таблицу:

Все Python и PHP разработчики:
idfirst_namelast_namelanguagelevel
1ДмитрийВасильевpythonjunior
2ВалерийЮрьевphpmiddle
3АндрейУшаковpythonsenior
5НатальяКузнецоваpythonmiddle
6РусланИсаковphpsenior
7СергейМедведевphpjunior
8АлексейБорисовpythonmiddle

В итоговую таблицу попали и те и другие программисты. Отлично. Но давайте расширим условие. Скажем, нам нужны только middle разработчики на этих языках. Добавим:

SELECT * FROM team 
WHERE 
    basic_language = 'Python' OR 
    basic_language = "PHP" AND 
    level = "middle"

После выполнения мы получим такую таблицу:

Результат SQL-запроса:
idfirst_namelast_namelanguagelevel
1ДмитрийВасильевpythonjunior
2ВалерийЮрьевphpmiddle
3АндрейУшаковpythonsenior
5НатальяКузнецоваpythonmiddle
8АлексейБорисовpythonmiddle

И результат довольно странный, в итоговой таблице присутствуют также джуниоры и сеньоры. И дело в том, что операторы OR и AND имеют приоритет выполнения и у AND он выше. Поэтому в первую очередь база данных находит всех мидлов, которые пишут на PHP. Такому условию соответствует только одна запись, а далее срабатывает оператор OR, который добавляет всех Python-разработчиков.

То есть мы ищем ИЛИ мидлов на PHP, ИЛИ Python-разработчиков без указания их уровня владения языком. Поэтому в таблицу также попали джуниоры и сеньоры.

Чтобы решить поставленную задачу, нужно четко расставить приоритет с помощью скобок. Как в математике. Поместим скобки справа и слева от OR:

SELECT * FROM team 
WHERE 
    (basic_language = 'Python' OR 
    basic_language = "PHP") AND 
    level = "middle"

Теперь в таблице остались только мидлы на Python и PHP:

Результат SQL-запроса:
idfirst_namelast_namelanguagelevel
2ВалерийЮрьевphpmiddle
5НатальяКузнецоваpythonmiddle
8АлексейБорисовpythonmiddle

Каждый раз когда в одном запросе встречаются OR и AND, обращайте внимание на порядок выполнения, иначе можно легко получить неверные данные.

Вообще, даже не так, каждый раз когда у вас есть в запросе есть OR и AND применяйте скобки для расстановки приоритетов, даже если уверены в своём коде.

Такая практика позволит избежать неприятных логических ошибок.

Следующий урок

Урок 4. Сортировка результатов

В этом уроке вы научитесь сортировать итоговые результаты в возрастающем и убывающем порядке с помощью ORDER BY.

Посмотреть

Полный курс с практикой

  • 57 уроков
  • 261 задание
  • Сертификат
  • Поддержка преподавателя
  • Доступ к курсу навсегда
5400
-20%
4320 ₽
  • Можно в рассрочку

Регистрация

или
Письмо со ссылкой для доступа отправлено.
Проверьте почту.

Письмо не пришло? Посмотрите в спаме.
Регистрируясь, вы соглашаетесь с условиями предоставления услуг (пользовательское соглашение).