Базы данных. Шпаргалка про SQL
Базовый синтаксис
SELECT * FROM table;
Чуть сложнее:
SELECT field_1, field_2 FROM table WHERE condition;
Примеры с JOIN
-ом таблиц (найти все имена пользователей, которым Иван отправлял сообщения)
SELECT u2.name
FROM users u1
JOIN messages m
ON m.sender_id = u1.id
JOIN users u2
ON m.receiver_id = u2.id
WHERE u1.name = "Ivan"
Фактически JOIN
создаёт в памяти новую таблицу — Декартово произведение исходных таблиц, и фильтрует её по условию, которое указано после слова ON
(как правило, там говорится, как склеить одну таблицу с другой; обычно по равенству каких-нибудь идентификаторов типа messages.sender_id = user.id
). А потом таблица дополнительно фильтруется условиями WHERE
и другими операторами. И в самом конце из получившейся таблицы выбираются только нужные нам колонки.
Не нужно беспокоиться, что полученная в результате JOIN таблица, будет большой. База данных сама придумает, как оптимизировать этот запрос и не делать лишней работы.
Обратите внимание, что мы пишем FROM <table_name> <alias_name>
(например FROM users u1
). Теперь таблица имеет «псевдоним» u1
(в рамках нашего запроса). Если одна и та же таблица нам нужна несколько раз, причём нам нужны разные строки (как таблица пользователей в примере про сообщения, которую мы использовали один раз для отправителя, другой — для получателя), мы просто даём два разных псевдонима.
С результирующей таблицей можно проделать разные вещи, прежде чем возвращать её. Например, если нужно, чтобы имена не повторялись,
SELECT u2.name
меняем на
SELECT DISTINCT(u2.name)
Или не возвращать таблицу, а только посчитать число строк SELECT COUNT(*)
. Сумма по столбцу: SELECT SUM(price)
итд.
Что ещё может понадобиться:
SELECT * FROM table LIMIT 5
— взять первые 5 строк получившейся таблицы
SELECT * FROM messages ORDER BY date ASC
— отсортировать сообщения по возрастанию (ascend) даты. Бывает ещё DESC
(descend), который сортирует по убыванию
Часто эти модификаторы объединяют. Например, чтобы найти самый дорогой предмет, мы отсортируем по цене по убыванию и возьмём одну верхнюю строку:
SELECT * FROM items ORDER BY price DESC LIMIT 1
Бывает ещё так, что нам нужно взять сто элементов, но не первые, а например третьи, т.е. строки 200–300 (для того, чтобы разбить данные на страницы по 100 строк). Для этого есть «сдвиг», OFFSET
:
SELECT * FROM messages ORDER BY date ASC LIMIT 100 OFFSET 200
Но если вы делаете OFFSET обязательно нужно сначала отсортировать, т.к. в разных запросах порядок может быть разный.
Условия можно комбинировать при помощи логических операторов
WHERE id = 42 or id = 137
или
WHERE sender_id = 1 AND date = "2021-12-13"
Есть операторы сравнения:
WHERE price < 100
WHERE age BETWEEN 14 AND 18
Можно проверить, что элемент — один из списка
WHERE id IN (1,2,3)
Можно проверить, что строка подходит под шаблон
name LIKE "Ivan %"
Сгруппировать строки таблицы по какому-то полю (после этого работать можно только с группами, не с отдельными строками)
GROUP BY field
Например, сколько сообщений отправил каждый пользователь за последний год:
SELECT u.name, COUNT(*) AS num_messages
FROM users u JOIN messages m ON m.sender_id = u.id
WHERE m.date BETWEEN '2020-12-13' AND '2021-12-13'
GROUP BY u.name
Есть ещё более хитрые штуки. Например, условие на то, что в группе не меньше 3 элементов пишется после GROUP BY
так:
GROUP BY u.id HAVING COUNT(*) > n
HAVING
— это такой WHERE
, но не для отдельных строк, а для групп.