. Техническое собеседование: 10 каверзных вопросов по SQL
Техническое собеседование: 10 каверзных вопросов по SQL

Техническое собеседование: 10 каверзных вопросов по SQL

Здравствуйте, коллеги. Представляю вам небольшую подборку каверзных вопросов по нашему любимому языку структурированных запросов. Список составлен на основе моего собственного опыта работы и хождения по собеседованиям. Я старался отбирать только те вопросы, ответы на которые могут помочь на практике, а не только на техническом собеседовании. Вопросы касаются базовых механизмов языка, потому в первую очередь будут интересны новичкам, но, возможно, и матерые разработчики узнают из них что-то новое. Итак, приступим.

1. Что вернет условие 2 <> NULL ?

Сравнение с NULL — это, наверное, первый подводный камень, на который натыкаются люди при работе с базой данных. Вопреки привычной логике условие

возвращает ложь (FALSE) , как впрочем и условие

Дело здесь в том, что тип значения NULL в SQL имеет несколько другой оттенок значения, чем в прикладных языках программирования. Если в С-подобных языках NULL значит отсутствие какого-то значения, то в SQL он значит лишь то, что мы не знаем этого значения. По этой причине любое сравнение с NULL возвращает ложь.

Возвращаясь к сути вопроса, мы не можем сказать «Два не равно NULL » потому, что мы не знаем значения справа от знака неравенства, а там как раз может оказаться двойка.

2. Что вернет условие 3 NOT IN (1, 2, NULL) ?

Здесь та же история, что и в предыдущем случае. Условие

3 NOT IN (1, 2, NULL)

возвращает ложь (FALSE), как и условие

Причина этого заключается в особенностях работы оператора IN . Проверяя, что определенное значение входит в коллекцию, оператор IN просто сравнивает это значение с каждым элементом коллекции.

это то же самое, что и

(3 = 1) OR (3 = 2) OR (3 = NULL)

В случае с NOT IN условие:

3 NOT IN (1, 2, NULL)

это то же самое, что и

Как мы знаем из предыдущего примера, 3 <> NULL возвращает ложь, а значит и все условие (3 <> 1) AND (3 <> 2) AND (3 <> NULL)

тоже будет ложным.

3. Выполнится ли этот запрос?

Едино правильного ответа на этот вопрос нет — все зависит от базы данных. Проблема этого запроса заключается в том, что колонка order_code не указана в выражении GROUP BY и при этом для нее не определена агрегатная функция. То есть по отношению к колонке order_code мы не знаем группировать ее или группировать по ней.

Если этот запрос будет выполняться в MySQL, то колонка order_code добавится в выражение GROUP BY автоматически и запрос выполнится нормально. Если же этот запрос будет выполняться MS SQL Server, то по умолчанию будет сгенерирована ошибка. Впрочем, это поведение настраивается.

4. Почему не выполнится этот запрос?

Запрос не выполнится из-за обращения к псевдониму year_of_birth в выражении WHERE . Дело в том, что псевдонимы полей в SQL используются для форматирования данных уже полученных из базы. Поэтому их можно использовать только в выражениях, которые отвечают за оформление результата, таких как GROUP BY , ORDER BY и HAVING . В выражениях, отвечающих за получение данных, таких как WHERE , нужно использовать оригинальные имена полей.

5. Имеет ли значение порядок колонок в составном индексе?

CREATE NONCLUSTERED INDEX MyInd on users (user_name, user_birth_date);

это не то же самое, что

CREATE NONCLUSTERED INDEX MyInd on users (user_birth_date, user_name);

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

Другими словами, колонки, по которым поиск выполняется чаще всего, должны стоять в составном индексе первыми.

6. Какая разница между TRUNCATE TABLE table_name и DELETE FROM table_name?

Фактически обе эти команды вызовут удаление всех строк из таблицы под названием table_name , но вот произойдет это совсем по-разному:

  1. При вызове команды TRUNCATE таблица полностью сбрасывается и создается снова, в то время как команда DELETE удаляет каждую строку таблицы по отдельности. Из-за этого TRUNCATE отрабатывает значительно быстрее.
  2. Как следствие первого пункта, команда TRUNCATE не вызывает срабатывание триггеров и правил внешних ключей, то есть, очищая таблицу таким способом, можно не бояться каскадного удаления или изменения данных в других таблицах.
  3. В отличие от DELETE команда TRUNCATE не транзакционная. То есть, если в момент ее вызова, таблица table_name будет заблокирована какой-либо транзакцией — может возникнуть ошибка.
7. Какая разница между типами CHAR и VARCHAR?

Оба эти типа используются для хранения текстовой информации ограниченной длины, а различия между ними следующие:

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

Тип VARCHAR хранит значение переменной длины. Под каждое значение этого типа выделяется столько памяти, сколько нужно для этого конкретного значения.

Таким образом, тип CHAR подходит для хранения строковых данных фиксированной длины (например, инвентарных номеров, хешей), а для остальных строк больше подойдут VARCHAR или NVARCHAR .

8. Какая разница между типами VARCHAR и NVARCHAR ?

Тип NVARCHAR , пожалуй, самый универсальный из строчных типов данных в БД. Он позволяет хранить строки переменной длины в формате Unicode. В этом формате каждый символ занимает 2 байта, а сама кодировка содержит 65 536 символов и включает в себя все языки мира, в том числе иероглифы.

Тип VARCHAR хранит данные в формате SACII. В этом формате каждый символ занимает 1 байт, но отельная кодировка содержит всего 256 символов. Из-за этого для каждого мирового языка выделяется своя кодировка.

Таким образом, в формате VARCHAR стоит хранить строчные данные, которые точно не придется переводить (например, адреса электронной почты). Для других случаев больше подойдет NVARCHAR .

9. Какая разница между UNION и UNION ALL ?

Выражения UNION и UNION ALL — это очень надежные поставщики лишних или недостающих строк в результате запроса. Оба эти выражения используются, чтобы объединить результаты нескольких независимых друг от друга запросов. А разница между ними заключается в том, что, если в результатах запросов есть одинаковые строки, то UNION удалит дубликаты, оставив только одну из таких строк. В то же время UNION ALL , как можно догадаться из названия, просто объединит результаты запросов, не обращая внимания на дубликаты.

10. Какая разница между выражениями WHERE и HAVING ?

Ну и наконец, вопрос, который задают практически на каждом собеседовании по базам данных: про HAVING .Выражения WHERE и HAVING используются для фильтрации результата запроса и ожидают после себя некоторое условие, по которому нужно отфильтровать данные. Но, если WHERE работает само по себе и фильтрует данные каждой строки результата по отдельности, то выражение HAVING имеет смысл только в сочетании с выражением GROUP BY и фильтрует уже сгруппированные значения.

Спасибо за внимание. Пишите в комментариях, на сколько вопросов вы знали ответ, а также с какими хитрыми задачами по SQL вам самим приходилось сталкиваться.

Підписуйтеся на Telegram-канал «DOU #tech», щоб не пропустити нові технічні статті.

До обраного В обраному 6

Схожі статті Горизонтальное масштабирование для SQL Server баз данных: как это сделать

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

Співбесіда з DevOps. 300+ запитань для Junior, Middle, Senior

Можна сперечатися про популярність DevOps, а можна просто готуватися до співбесіди та отримати омріяні 9K :) Щоб допомогти вам зорієнтуватись у питаннях, які ставлять на інтерв’ю, ми поспілкувались з тими, хто їх проводить, і склали список можливих запитань. 115

Співбесіда з Python. 100+ запитань для Junior, Middle, Senior

Редакція DOU поспілкувалась з розробниками, що проводять технічні співбесіди для різних рівнів Python-спеціалістів, і зібрала приблизний список запитань для кандидатів. У матеріалі є і теоретичні питання, і практичні задачі. 50

DOU News #12

Найкращі коментарі пропустити

«Каким вы видите свой запрос через 5 лет?»

Автору спасибі, хоч якась цікава технічна тема, бо все про трактори і ’бест практіси’ від новоспечених сеньйорів.

а где каверзные вопросы?

Эти вопросы каверзные только если вы прогуляли курс баз данных или принадлежите к модной когорте «нам не нужно образование».

В ней написано, в частности:

Some people are under the misconception that Unicode is simply a code where each character takes 16 bits and therefore there are 65,536 possible characters. This is not, actually, correct. It is the single most common myth about Unicode, so if you thought that, don’t feel bad.

Вот есть русский перевод, если не осиливаете оригинал.

181 коментар

любопытно. можешь выложить?

не, ну, в UNION из одной части в другую данные не кочуют. Что с подзапросами, что без.

а ну-ка пример субд в которой так алиасы работают? или это лишь ваши фантазии?

та ну, exists, any, all нормально работают без алиасов. требуется только для derived table.

Помечтайте. Varchar займёт в аккурат на 2 байта больше того же типа CHAR. Всё та же строка, дополненная пробелами. Она просто усекается при выдаче. Но уж точно не двигает всю таблицу при изменении значения в строке.Хотите переменного значения — BLOBы ваше всё, естественно с последствием в виде ну очень проблемного их восстановления в случае если посыпался индекс.

Это жестоко по отношению к новичкам. И что ещё хуже, этой статьёй могут воспользоваться ХРюши и манагеры с целью тестирования.Любая логика над NULL вернёт NULL.

А вот это уже скотство от создателей SQL (Оракла то бишь). Операция IN не является логической, это предикат над множеством. Почему множество, поданное списком, принципиально отличается от того же множества, поданного таблицей — а null его знает.

Я к примеру об этой гомосятине узнал только что из статьи, хотя программирую уж почти пару десятков лет. И тому есть простое объяснение:Использовать IN противопоказано в боевом программировании. Просто забудьте о его существовании, равно как и про BETWEEN. Обе эти операции гарантируют вам построчное сканирование таблицы, то есть заведомый промах по всем индексам. Даже если в условии задано выражение, на индекс попадающее, нередки случаи когда оптимизатор принимает решение о полном сканировании. Да, это тупизм от создателей оптимизаторов (Майкрософт в этом особо отличиться умеет), но для оптимизатора наличие в запросе колонки из индекса — говорит что в индекс он попал, а потом операция не поддающаяся индексации — и жопа.

Почему BETWEEN не применяет индекса — великое ХЗ, но тот же запрос с «больше равно» и «меньше равно» в индексы попадёт гарантированно. Но с IN — не попадёт, даже если будет пустое множество в скобках, всё равно будут просмотрены все строки.

index range scan уже отменили?

Не знаю как в других ДБ, но Оракл перепишет BETWEEN как >= <= и будет использовать индекс, если он конечно есть.

Вообще задавать такие вопросы без привязки к конкретной ДБ глупо, как и задавать такие вопросы web developerу.Сначала в погоне за фулстеком web developerы понаписывают запросы, а потом удивляются почему в продакшене все тормозит.Кесарю кесарево в общем.

вы не уточнили СУБД, но для SQL Server написанное выше — ахинеяdocs.microsoft.com/. ​-sql?view=sql-server-2017

char [ ( n ) ] Fixed-length, non-Unicode string data. n defines the string length and must be a value from 1 through 8,000. The storage size is n bytes. The ISO synonym for char is character.

varchar [ ( n | max ) ] Variable-length, non-Unicode string data. n defines the string length and can be a value from 1 through 8,000. max indicates that the maximum storage size is 2^31-1 bytes (2 GB). The storage size is the actual length of the data entered + 2 bytes.

для оракла честно говоря не нашел в документации как он раельно хранит varchar

ну опять таки, для SQL Server написанное выше полнейший бред (как в смысле написанного так и в стиле изложения) — индекс может не использоваться запросом в том случае если оптимизатор решит что его дешевле просканировать. почему он так решит причин может быть множество — селективность индекса низкая, статистика устаревшая, какой джойн используется (nested loop, merge, hash). единственно сделаю оговорку — с фильтрованными индексами ситуация может быть несколько иной, там действительно были проблемы когда индекс не использовался хотя должен был бы. но вроде как минимум часть этих проблем порешали

Список в худших традициях украинских собеседований.Первая половина — нафуй не нужные вопросы, не встречаются в реале. Нужны для того, чтобы потешить ЧСВ собеседюущего. Он то знает на них ответы, а заваленные им кандидаты — нет.Вторая половина — трюизмы, которые знает любой SQL-Developer уровня Junior.

Параметр order_code автоматически НЕ добавляется к GROUP BY. Иными словами MySQL НЕ переписывает запрос

SELECT A, B, COUNT(*) FROM T GROUP BY A

как вы написали в запрос:

SELECT A, B, COUNT(*) FROM T GROUP BY A, B

Можете потестировать взяв в качастве A/B primary key — тогда б вам COUNT(*) всегда выдавал, но нет :)

Тут скорее интересен вопрос, что вообще MySQL это допускает и что в итоге выдаст в колонке B.

Потому осторожно пользуемся, а то потом придется переписывать код или ломать голову откуда вылезли непонятные значения в колонке B

Почитать тут и тоже самое глянуть в версиях !=5.7: dev.mysql.com/. ​en/group-by-handling.html

А как у ДОУ с модерацией технических статей? В конкретно этой приводится в корне не верное объяснение причин поведения null в логических выражениях, смысл TRUNCATE, смысл алиаса колонки, описание WHERE и HAVING. Как минимум.

ЗЫ: а почему только технических? #trollface

))) список источников почти везде уместен, а в технической статье имхо необходим

а на доу есть технические статьи?

Яка крайина таки и статти ))

Вопрос очень правильный, единственно, хотел бы акцентировать Ваше внимание но один момент.

Автор описфвает что сие есть для собеседования.Вот тут вот большой кейс.

Часто испытуемых можно разделить на две групы.

Первая — это грамотные практики, которые «капают теорию» ровно на столько, на сколько это практически нужно. Они дают правильные ответы и их ответы подкреплены реальным опытом. Они искали ответ на вопрос «почему» и ограничились «первым приближением».

Вторая — это, если обобщенно, математики.Они знают, или понимают, или чувствуют, что математика — наука архисложная. А програмирование так или иначе — прикладная математика.И тут новый кейс, еще две группы:—"академики" — люди с глубокими академическими знаниями, которые «не терпят» «приближенных наименований» и «не четких определений, описаний». Для них рабочий код может «работать не правильно», потому что по сути «работать не должен». И они, имея глубочайшие познания" «всегда правы», какой бы ценой это выражалось. —"энтузиасты" — фанаты, для которых маиематика — это религия («возлюбленная Богиня»), красота которой в ее строгости, гармоничности и закончености логических линий. Рефакторинг кода они будут делать до тех пор, пока весь код не будет лаконичен как украинское «Будьмо!».

Эффективность работы любой команды девов в сбалансированом количестве людей этих груп.На собеседовании важно определить — а каков испытуемый. Возможно это и имел в виду автор, тем более что как раз второй группе это рассказывать нету смысла. Они знают. Возможно лучше него.

Если мы проанализируем любой холивар — вот это скорее всего разные стороны — представители этих групп.

Я лично столкнулся с «проблемой этих груп», когда, работая в SoftBistro, написал статью про noSQL Cassandra, одним из тезисов которой было то, что Cassandra ближе к Релятивной модели баз данных, чем SQL.

Для людей «первой группы», «не копающих глубоко», SQL тождественно Релятивной модели баз данных.Для людей «второй группы», «копаюших строго и глубоко», SQL всего лишь simple (и ПОКА единственная) реализация Релятивной модели баз данных.

📎📎📎📎📎📎📎📎📎📎