Базовый запрос SELECT
Вот пример одного из самых распространенных запросов SQL:
SELECT *
FROM Pets;
Результат:
+---------+-------------+-----------+-----------+------------+
| PetId | PetTypeId | OwnerId | PetName | DOB |
|---------+-------------+-----------+-----------+------------|
| 1 | 2 | 3 | Fluffy | 2020-11-20 |
| 2 | 3 | 3 | Fetch | 2019-08-16 |
| 3 | 2 | 2 | Scratch | 2018-10-01 |
| 4 | 3 | 3 | Wag | 2020-03-15 |
| 5 | 1 | 1 | Tweet | 2020-11-28 |
| 6 | 3 | 4 | Fluffy | 2020-09-17 |
| 7 | 3 | 2 | Bark | NULL |
| 8 | 2 | 4 | Meow | NULL |
+---------+-------------+-----------+-----------+------------+
Этот запрос выбирает все столбцы во всех записях таблицы
. Символ звездочка (Pets
) является шаблоном и обозначает, что мы хотим получить все столбцы из таблицы.*
Выбираем столбцы по именам

Для повышения производительности запросов обычно выбирают не все имеющиеся в таблице столбцы, а только те, которые нужны в данный момент. Вот пример:
SELECT PetId, PetName
FROM Pets;
Результат:
+---------+-----------+
| PetId | PetName |
|---------+-----------|
| 1 | Fluffy |
| 2 | Fetch |
| 3 | Scratch |
| 4 | Wag |
| 5 | Tweet |
| 6 | Fluffy |
| 7 | Bark |
| 8 | Meow |
+---------+-----------+
Фильтруем выборку данных

Чтобы получить только те строки, которые нам нужны, мы можем добавить в запрос оператор
.WHERE
SELECT PetId, PetName
FROM Pets
WHERE PetName = 'Fluffy';
Результат:
+---------+-----------+
| PetId | PetName |
|---------+-----------|
| 1 | Fluffy |
| 6 | Fluffy |
+---------+-----------+
Вот еще один пример фильтрации выборки. На этот раз мы будем использовать операцию «больше» (
), чтобы получить записи с днем рождения питомца позже определенной даты (DOB, date of birth – дата рождения).>
SELECT PetName, DOB
FROM Pets
WHERE DOB > '2020-01-01';
Результат:
+-----------+------------+
| PetName | DOB |
|-----------+------------|
| Fluffy | 2020-11-20 |
| Wag | 2020-03-15 |
| Tweet | 2020-11-28 |
| Fluffy | 2020-09-17 |
+-----------+------------+
Вы можете заменить операцию «больше» на любую другую, например, на «больше либо равно (
), «меньше» (>=
<
) или «меньше либо равно» (
).<=
Для получения значений, попадающих в некоторый диапазон, можно использовать оператор
(например, день между датой начала и конца интервала).BETWEEN
SELECT
PetName,
DOB
FROM Pets
WHERE DOB BETWEEN '2018-01-01' AND '2020-01-01';
Результат:
+-----------+------------+
| PetName | DOB |
|-----------+------------|
| Fetch | 2019-08-16 |
| Scratch | 2018-10-01 |
+-----------+------------+
Сортировка результатов запроса

Чтобы отсортировать записи, возвращаемые запросом, мы можем добавить в запрос оператор
.ORDER BY
Сортировка в порядке возрастания
Для сортировки записей в порядке возрастания необходимо использовать ключевое слово
(ascending – возрастание). Такой порядок используется по умолчанию, поэтому ключевое слово в запросе можно не указывать.ASC
SELECT PetId, PetName
FROM Pets
ORDER BY PetName ASC;
или короче
SELECT PetId, PetName
FROM Pets
ORDER BY PetName;
Результат:
+---------+-----------+
| PetId | PetName |
|---------+-----------|
| 7 | Bark |
| 2 | Fetch |
| 1 | Fluffy |
| 6 | Fluffy |
| 8 | Meow |
| 3 | Scratch |
| 5 | Tweet |
| 4 | Wag |
+---------+-----------+
Сортировка в порядке убывания
Для получения результата запроса в порядке убывания нужно использовать ключевое слово
.DESC
SELECT PetId, PetName
FROM Pets
ORDER BY PetName DESC;
Результат:
+---------+-----------+
| PetId | PetName |
|---------+-----------|
| 4 | Wag |
| 5 | Tweet |
| 3 | Scratch |
| 8 | Meow |
| 1 | Fluffy |
| 6 | Fluffy |
| 2 | Fetch |
| 7 | Bark |
+---------+-----------+
Сортировка по нескольким столбцам
Чтобы отсортировать записи по нескольким столбцам, их имена нужно перечислить через запятую.
SELECT PetId, PetName
FROM Pets
ORDER BY PetName ASC, PetId ASC;
SELECT PetId, PetName
FROM Pets
ORDER BY PetName ASC, PetId DESC;
Результат:
+---------+-----------+
| PetId | PetName |
|---------+-----------|
| 7 | Bark |
| 2 | Fetch |
| 1 | Fluffy |
| 6 | Fluffy |
| 8 | Meow |
| 3 | Scratch |
| 5 | Tweet |
| 4 | Wag |
+---------+-----------+
(8 rows affected)
+---------+-----------+
| PetId | PetName |
|---------+-----------|
| 7 | Bark |
| 2 | Fetch |
| 6 | Fluffy |
| 1 | Fluffy |
| 8 | Meow |
| 3 | Scratch |
| 5 | Tweet |
| 4 | Wag |
+---------+-----------+
(8 rows affected)
Обратите внимание, что две записи с именем питомца
расположены в разном порядке (это видно по значению в поле Fluffy
). Это произошло потому, что в запросах сортировка производится сначала по столбцу PetId
PetName
, а затем уже по столбцу
.PetId
Сортировка по скрытым столбцам
Вы можете отсортировать результат запроса по столбцам, которые не входят в список выборки, расположенный после оператора
.SELECT
SELECT PetId, PetName
FROM Pets
ORDER BY DOB DESC;
Результат:
+---------+-----------+
| PetId | PetName |
|---------+-----------|
| 5 | Tweet |
| 1 | Fluffy |
| 6 | Fluffy |
| 4 | Wag |
| 2 | Fetch |
| 3 | Scratch |
| 7 | Bark |
| 8 | Meow |
+---------+-----------+
По этой выборке мы можем сделать вывод, что
– самый младший питомец, а Tweet
– самый старший, потому что мы отсортировали записи по дате рождения (DOB) в порядке убывания.Meow
Чтобы убедиться давайте, выполним запрос, добавив столбец DOB в список
.SELECT
SELECT PetId, PetName, DOB
FROM Pets
ORDER BY DOB DESC;
Результат:
+---------+-----------+------------+
| PetId | PetName | DOB |
|---------+-----------+------------|
| 5 | Tweet | 2020-11-28 |
| 1 | Fluffy | 2020-11-20 |
| 6 | Fluffy | 2020-09-17 |
| 4 | Wag | 2020-03-15 |
| 2 | Fetch | 2019-08-16 |
| 3 | Scratch | 2018-10-01 |
| 7 | Bark | NULL |
| 8 | Meow | NULL |
+---------+-----------+------------+
Теперь мы видим, что дата рождения у питомцев
и Meow
имеет значение Bark
, поэтому на самом деле мы не знаем кто из них двоих младше.NULL
Этот пример показывает, что значение
является наименьшим из всех возможных. Об этом нужно помнить, составляя запросы.NULL
Отбор записей по текстовому шаблону

Для отбора записей по текстовому шаблону мы используем оператор
.LIKE
SELECT PetId, PetName
FROM Pets
WHERE PetName LIKE 'F%';
Результат:
+---------+-----------+
| PetId | PetName |
|---------+-----------|
| 1 | Fluffy |
| 2 | Fetch |
| 6 | Fluffy |
+---------+-----------+
В приведенном примере мы выбрали всех питомцев, чьи имена начинаются с буквы F. Знак процента (
) используется как шаблонный символ, показывающий, что дальше может идти строка из любого количества знаков, в том числе и пустая. Такой шаблонный символ может использоваться в начале строки, в конце её или даже в середине.%
Вот еще один пример:
SELECT FirstName, LastName, Email
FROM Owners
WHERE Email LIKE '%@example.%';
Результат:
+-------------+------------+-------------------------------------------------+
| FirstName | LastName | Email |
|-------------+------------+-------------------------------------------------|
| Homer | Connery | [homer@example.com](<mailto:homer@example.com>) |
| Bart | Pitt | [bart@example.com](<mailto:bart@example.com>) |
+-------------+------------+-------------------------------------------------+
Выбор из списка

Оператор
позволяет определить, что указанное значение входит в список или результат подзапроса. Рассмотрим пример.IN
SELECT
PetId,
PetName,
DOB
FROM Pets
WHERE PetName IN ('Fluffy', 'Bark', 'Wag');
Результат:
+---------+-----------+------------+
| PetId | PetName | DOB |
|---------+-----------+------------|
| 1 | Fluffy | 2020-11-20 |
| 4 | Wag | 2020-03-15 |
| 6 | Fluffy | 2020-09-17 |
| 7 | Bark | NULL |
+---------+-----------+------------+
Подзапросы

Вы можете использовать оператор
вместе с подзапросами (запросами, вложенными внутрь другого запроса). Например:IN
SELECT
PetTypeId,
PetType
FROM PetTypes
WHERE PetTypeId IN (SELECT PetTypeId FROM Pets);
Результат:
+-------------+-----------+
| PetTypeId | PetType |
|-------------+-----------|
| 1 | Bird |
| 2 | Cat |
| 3 | Dog |
+-------------+-----------+
Этот запрос возвращает только те виды питомцев из таблицы
, которые используются в таблице PetTypes
. Чтобы продемонстрировать это более наглядно, ниже показано содержание этих двух таблиц.Pets
Таблица PetTypes
+-------------+-----------+
| PetTypeId | PetType |
|-------------+-----------|
| 1 | Bird |
| 2 | Cat |
| 3 | Dog |
| 4 | Rabbit |
+-------------+-----------+
Таблица Pets
+-------------+-----------+
| PetTypeId | PetName |
|-------------+-----------|
| 2 | Fluffy |
| 3 | Fetch |
| 2 | Scratch |
| 3 | Wag |
| 1 | Tweet |
| 3 | Fluffy |
| 3 | Bark |
| 2 | Meow |
+-------------+-----------+
Мы видим, что таблица PetTypes
содержит вид
, но ни одному из домашних животных в таблице Rabbit
Pets
не был присвоен этот тип (то есть в столбце PetTypeId
таблицы Pets
нет значения 4).
Соединения

Можно спорить о том, считаются ли SQL-соединения «базовыми» SQL-запросами, но я все же решил включить их сюда.
В завершение этой статьи приведем пример внутреннего соединения.
SELECT
p.PetName,
pt.PetType
FROM Pets p
INNER JOIN PetTypes pt
ON p.PetTypeId = pt.PetTypeId;
Результат:
+-----------+-----------+
| PetName | PetType |
|-----------+-----------|
| Fluffy | Cat |
| Fetch | Dog |
| Scratch | Cat |
| Wag | Dog |
| Tweet | Bird |
| Fluffy | Dog |
| Bark | Dog |
| Meow | Cat |
+-----------+-----------+
В этом запросе мы использовали внутреннее соединение (
) чтобы получить имена всех питомцев с указанием вида каждого из них. После оператора INNER JOIN
ON
описано условие соединения (предикат), которое вычисляется для каждой пары соединяемых записей. В нашем случае столбец
является внешним ключом в таблице p.PetTypeId
, а столбец Pets
– первичным ключом в таблице pt.PetTypeId
. Чтобы сделать код более красивым и лаконичным мы применили псевдонимы для имен таблиц.PetTypes
Комментарии