Я много лет страстно увлечен базами данных и программированием на языке SQL. Поверьте, это просто и увлекательно, к тому же высокооплачиваемое умение.
Отвлекитесь ненадолго и полистайте мои практические беседы без теоретической шелухи. Пусть вас не удивляет нумерация разделов - я постарался изложить материал в наиболее полезной последовательности.
Содержание беседы #1:
Тема 2. Язык структурированных запросов
Раздел 2.1 Понятие Стандарта ANSI-SQL
Пункт 2.1.2 Основные команды языка (Select, From)
Основные команды языка.
Когда мы говорим о Базе данных, мы должны понимать: физически, информация хранится на устройстве долгосрочного хранения на сервере.
Получить доступ к необходимой информации можно лишь через отправку команды серверу. Так как объем данных может быть велик, а структура информации сложна и разнопланова – синтаксис подобной команды должен быть гибким и богатым.
Команда для сервера баз данных называется Запросом. Синтаксис запроса формализован в виде специального языка программирования – Языка структурированных запросов (SQL).
Гениальность идеи языка подтверждается двумя с виду противоречащими факторами – простотой и мощностью.
Наиболее наглядно оба фактора проявляются в основной команде языка – команде выбора данных.
Простейший вид команды должен содержать зарезервированное слово Select. Это необходимое условие, в редких случаях бывающее достаточным.
Ниже представляю допустимые разновидности команды.
Вернуть простую константу:
Select 1
Select ‘a’
Вернуть результат функции:
Select getdate()
Вернуть результат подзапроса:
Select (Select count(*) from Table1)
Такой вид запроса является редко используемым. Особенности:
· во всех перечисленных случаях источник данных указан неявно;
· строка возвращается ровно одна.
Количество столбцов может быть несколько – их необходимо перечислить через запятую.
Намного чаще необходима вторая часть команды, явно указывающая на источник, оператор From:
Select * From Table1
Select * From Table1 as t1 Join Table2 as t2 On t1.column1 = t2.column1
Select * From (Select column1 From Table1) as t1
Источником данных может быть только таблица или подзапрос, результат которого считается подобием таблицы.
Наконец, самая интересная третья часть команды – оператор условий Where:
Select * From Table1 Where <набор логических условий>
Эти три команды должны встретиться в запросе именно в такой последовательности, т.е. разрешены варианты:
Select…
Select… From…
Select… From… Where…
Но некорректны варианты:
Select… Where…
From…
Where…
Далее могут быть использованы еще два блока, каждого из которых может и не быть, но в указанной последовательности: Group By (группировка), Order By (сортировка). Дополнительно, после группировки могут быть наложены дополнительные условия через оператор Having.
Никаких других блоков у команды выбора данных Стандартом не определено. Так что можете выдохнуть)
Каждый блок имеет свои особенности при написании кода, поэтому, прежде всего, программисту-хипстеру нужно четко понимать: над каким блоком он сейчас работает.
Рассмотрим каждый блок в отдельности. Логически правильнее произвести рассмотрение в той последовательности, в которой ядро СУБД будет анализировать запрос: сначала определяется источник (From), затем условия отбора данных (Where), потом, если есть, происходит группировка данных (Group By), наложение дополнительных условий посредством Having, затем получение результирующего вывода данных для пользователя (Select), наконец сортировка этих данных, если необходимо (Order By).
Оператор From. Источник данных может быть фиктивным, реальной таблицей или подзапросом (все три варианты продемонстрированы выше).
Если таблица указывается одна, то синтаксис тривиален. Сложности начинаются, когда требуется соединить две или более таблиц. Для этого указывается специальный оператор – Join. Он может быть аж четырех видов. Всё дело в том, что данные разбиты по таблицам согласно правилам нормализации, а оператор Join как бы производит обратное действие соединяя все данные.
Пусть у нас есть две тестовые таблицы.
Table1 – справочная. Специально вывод произведен без сортировки, чтобы указать, что это не важно для операций с данными, только для восприятия пользователя.
column1 name
2 ‘b’
1 ‘a’
3 ‘c’
Table2 – отражает некий процесс над объектами из Table1.
column1 value
3 5
3 10
1 10
Первый, основной и самый простой вид соединения – прямое Inner Join. Если слово Inner опустить, то по умолчанию СУБД считает, что соединение именно прямое.
Select * from Table1 as t1 Join Table2 as t1 On t1.column1 = t2.column1
Результатом такого запроса будет:
1 ‘a’ 1 10
3 ‘c’ 3 5
3 ‘c’ 3 10
Скорее всего, эти две таблицы по схеме данных соединены связью один-ко-многим именно по полю column1, поэтому мала вероятность, что они будут соединены по иным полям. Я рассуждаю даже не приводя схему данных, я даже мог бы не писать что одна из них справочная, и не приводить значения, которыми они заполнены. Просто если мы видим написанное соединение – мы с высокой долей вероятности знаем про эти подробности. И наоборот: мы сами так и только так должны соединять эти таблицы, повторю за исключением редчайших случаев нетривиального анализа данных.
Как видишь, друг-хипстер, разобраться в основах языка не сложнее, чем расчесать бороду утром)
Зато может понадобиться применить другой вид соединения.
Второй вид соединения – левое Left Join.
Select * from Table1 as t1 Left Join Table2 as t2 On t1.column1 = t2.column1
Результатом такого запроса будет:
1 1 10
3 3 5
3 3 10
Если при прямом соединении таблицы можно было бы обменять местами и результат не изменится, то при левом соединении первая таблица оказывается как бы ведущей, а вторая ведомой.
Результатом такого запроса будет:
1 ‘a’ 1 10
3 ‘c’ 3 5
3 ‘c’ 3 10
2 ‘b’ Null Null
Добавилась одна строка: из ведущей таблицы строки будут выведены все, а при отсутствии значения по связываемому полю column1 – пустота, отсутствие значения.
Теперь обменяем таблицы местами, чтобы убедиться, что такая перестановка равноценна прямому соединению.
Select * from Table2 as t2 Left Join Table1 as t1 On t2.column1 = t1.column1
Результатом такого запроса будет:
1 10 1 ‘a’
3 5 3 ‘c’
3 10 3 ‘c’
Правое соединение обладает такими же свойствами, что и левое, только вторая из указанных таблиц становится ведущей.
Важно понять: нет такой задачи которую можно было бы решить с помощью правого соединения и нельзя с помощью левого, более того – все задачи можно решить не прибегая ни к правому, ни к левому соединению. Задачи с участием более чем одной таблицы решаются через прямое соединение или через подзапросы, о чем будет подробно рассказано в соответствующем разделе «Виды запросов».
Есть еще одна разновидность соединения, которая покрывает собой оставшиеся варианты соединения таблиц, т.е. никакого другого способа нет и не придумать. Полное соединение. У него есть два синонима в написании, но логически они означают одно и то же.
Select * from Table1 as t1 Full Join Table2 as t1 On t1.column1 = t2.column1
Select * from Table1 Cross Join Table2
Каждая запись из первой таблицы соединится с каждой записью из второй таблицы.
Результат соединения:
1 ‘a’ 1 10
1 ‘a’ Null Null
1 ‘a’ Null Null
3 ‘c’ 3 5
3 ‘c’ 3 10
3 ‘c’ Null Null
2 ‘b’ Null Null
2 ‘b’ Null Null
2 ‘b’ Null Null
Даже совершенно не подходящие друг другу строки соединились. Такое соединение используется редко. Оно также называется декартовым произведением.
Если вы усвоили первую беседу, то можете смело отправляться на собеседование по вакансии "младший SQL-программист". Хотите большего - читайте следующие беседы.
Спасибо, что дочитали до конца! Любите друг друга... и базы данных)
Автор: Щукин Андрей (vk.com/faustonly), Санкт-Петербург. Дата публикации: 22.02.2018