бесплатно без регистрации урок 2 из 18

SELECT: выбрать колонки

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

17 мин чтения · 4 главы ·4 задания ·домашняя работа

Список колонок и звёздочка

Запрос начинается со списка колонок. Пишут их через запятую сразу после слова SELECT, а после FROM — имя таблицы, откуда их брать.

SELECT title, price
FROM products

Пятнадцать строк, две колонки. Первые из них выглядят так:

titleprice
Ноутбук Pro 1489990
Смартфон X54990
Наушники Air12990
Клавиатура Mech7490
Тот же запрос, тот же результат: его можно скопировать и проверить.

Главное, что стоит заметить: строк осталось пятнадцать — столько же, сколько в таблице. Список после SELECT вырезает из таблицы вертикальную полосу и не трогает строки вовсе. Отсекать строки будет WHERE, и это следующий урок.

таблица products15 строк5 колонокSELECT title, price15 строк2 колонкиSELECT *15 строк5 колонокстрок всегда столько же: их отсекает не SELECT, а WHEREпорядок колонок в результате — тот, в каком вы их перечислилизвёздочка означает «все колонки в порядке таблицы»
Список после SELECT вырезает из таблицы вертикальную полосу: строк остаётся столько же.

Порядок колонок в результате — тот, в каком вы их перечислили, а не тот, в каком они лежат в таблице. SELECT price, title даст сначала цену, потом название. Для глаз это мелочь, а для программы, которая читает результат по номеру колонки, — нет.

Вместо списка можно написать звёздочку: SELECT * FROM products вернёт все пять колонок в том порядке, в каком они объявлены в таблице.

Ещё две мелочи, которые пригодятся сразу.

Одну и ту же колонку можно перечислить дважды — база не возражает: SELECT title, title FROM products вернёт две одинаковые колонки. Само по себе это не нужно, но перестаёт удивлять, когда такое встречается в чужом запросе после правки.

А имя колонки, которой в таблице нет, — это ошибка, и база скажет о ней сразу, до всякого выполнения. Ошибиться в имени легко: name есть у покупателей и сотрудников, а у товаров колонка называется title. Такие ошибки — самые дешёвые: они находятся в первую секунду.

Колонку можно называть вместе с таблицей, через точку: products.title. Пока таблица одна, это лишние буквы, и так почти не пишут. Но как только в запросе появится вторая таблица, выяснится, что колонка id есть у обеих, — и без уточнения база не поймёт, о какой из них речь. Привыкать заранее не нужно; достаточно знать, что запись законна и что она означает.

И вопрос, который стоит решить сразу: сколько колонок брать. Ответ короткий — ровно те, что нужны. Каждая лишняя колонка это данные, которые база прочитала, передала по сети и показала, а читатель пролистал. На пятнадцати товарах разница неощутима, на миллионе строк лишняя текстовая колонка превращает секунду в минуту.

Псевдонимы: имя колонки в ответе

Колонка в результате получает имя. По умолчанию это имя из таблицы — title, price. Заменить его можно псевдонимом: слово AS и новое имя.

SELECT title AS Товар, price AS Цена
FROM products

Данные при этом те же до последнего знака: меняется только подпись столбца в ответе.

в таблицеpriceв результатеЦена, ₽SELECT price AS "Цена, ₽" FROM productsданные не меняются: меняется только подпись столбцаимя из двух слов и с запятой берут в двойные кавычки
AS даёт колонке имя в результате; в таблице всё остаётся как было.

Зачем это нужно. Во-первых, результат запроса часто уходит человеку — в отчёт, в таблицу, в письмо, — и заголовок «price» там читается хуже, чем «Цена». Во-вторых, у вычисленной колонки своего имени нет вовсе, и без псевдонима она получит от базы что-нибудь вроде price * 0.9 — заголовок, который невозможно ни прочитать, ни использовать.

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

SELECT title AS "Название товара",
       price AS "Цена, ₽"
FROM products

Само слово AS необязательно: price Цена работает так же. Писать его всё же стоит — без него пропущенная запятая превращается в псевдоним и молча съедает колонку:

-- забыта запятая: две колонки вместо трёх
SELECT title, price stock
FROM products

Здесь база решит, что stock — это псевдоним для price, и вернёт колонку «stock», в которой лежат цены. Ни ошибки, ни предупреждения; ошибку находят потом, в отчёте, где остатки подозрительно похожи на цены.

И последнее: псевдоним нельзя использовать в том же SELECT, где он объявлен, — так же, как его нельзя использовать в WHERE. Причина та же: имена появляются все разом, в конце вычисления списка. Нужна колонка, посчитанная из другой вычисленной, — выражение повторяют целиком или разбивают запрос на два, и этому посвящён урок про подзапросы.

Псевдоним бывает не только у колонки, но и у таблицы — короткое имя после FROM:

SELECT p.title, p.price
FROM products AS p

Здесь это пока лишняя работа: таблица одна, и уточнять нечего. Смысл появится в уроке про соединения, где таблиц станет три, а у каждой найдётся колонка id. Тогда короткое имя из одной-двух букв окажется единственным способом написать запрос так, чтобы его можно было прочитать.

Правило то же, что у колонок: слово AS необязательно (FROM products p работает), а имя из одного слова пишут без кавычек. И то же предостережение: объявив псевдоним таблицы, дальше пользуются им. Смешивать в одном запросе p.title и products.title база разрешит не всегда, а прочитать такое не сможет никто.

Выражения в списке колонок

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

SELECT title,
       price,
       price * 0.9 AS "Цена со скидкой"
FROM products

У ноутбука за 89 990 в третьей колонке окажется 80 991. Строк по-прежнему пятнадцать: выражение считается для каждой строки отдельно и ничего не складывает между строками. Складывать умеют агрегаты, и до них ещё два урока.

что можнопримерчто получится
Арифметикаprice * 2число
Скобки и порядок(price + 100) * 2число
Делениеprice / 12число, но осторожно
Склейка текстаcity || ', ' || nameтекст
Число прямо в запросе0.9одно и то же во всех строках

Про деление стоит сказать отдельно, потому что на нём спотыкаются все. Во многих базах деление двух целых чисел даёт целое: 7 / 2 — это 3, а не 3,5. Дробная часть не округляется, а отбрасывается. Лечится это умножением на 1.0: 7 * 1.0 / 2 уже даст 3,5.

Склейка текста обозначается двумя вертикальными чертами:

SELECT name || ' (' || city || ')' AS "Покупатель"
FROM customers

Получится «Анна Смирнова (Москва)». Знаки препинания и пробелы пишутся отдельными кусочками текста в одинарных кавычках — база сама ничего не подставляет.

И ещё одна вещь, которая поначалу выглядит бессмыслицей: в списке колонок можно написать просто число или просто текст. SELECT title, 1 AS Проверено FROM products вернёт колонку из пятнадцати единиц. Пригождается это чаще, чем кажется: так помечают строки, пришедшие из разных источников, когда результаты двух запросов складывают вместе.

Порядок действий в выражении обычный, школьный: сначала умножение и деление, потом сложение и вычитание, скобки сильнее всего. price + 100 * 2 — это цена плюс двести, а не цена плюс сто, умноженная на два. Ошибка выглядит безобидно и не даёт о себе знать ничем, кроме неверного числа в отчёте, поэтому скобки ставят даже там, где можно не ставить.

И ещё одно, что пригодится в следующих уроках: выражения живут не только в списке колонок. Ту же арифметику можно написать в WHERE («где цена со скидкой больше десяти тысяч») и в ORDER BY («по сумме строки заказа»). Правила везде одни и те же — и целочисленное деление, и пустота в склейке ведут себя одинаково, в какой бы части запроса выражение ни стояло.

DISTINCT: только разные

Последнее, что умеет SELECT сам по себе, — убирать повторы. Слово DISTINCT ставится сразу после него и означает «оставить только разные строки».

SELECT DISTINCT category
FROM products

В таблице пятнадцать товаров, но категорий у них всего пять: электроника, аксессуары, бытовая техника, книги, мебель. Без DISTINCT запрос вернул бы пятнадцать строк, из которых «Электроника» встретилась бы пять раз.

category у 15 товаровЭлектроника · ЭлектроникаАксессуары · КнигиЭлектроника · …DISTINCT categoryЭлектроникаАксессуарыБытовая техника · Книги · Мебельпятнадцать строк превращаются в пять — по числу разных категорийDISTINCT category, price считает повтором совпадение обеих колонокпоэтому лишняя колонка в списке почти всегда ломает DISTINCT
Смотрит он на всю строку целиком, а не на одну колонку.

Это самый частый способ узнать, что вообще лежит в колонке. Незнакомая таблица, колонка status — что в ней бывает? Один запрос, и видно: done, cancelled, shipped, new, paid. Пять значений, и теперь можно писать условия, не гадая.

Второе, что стоит знать: пустота считается значением. Если в колонке есть незаполненные клетки, DISTINCT вернёт одну строку и для них тоже — и две пустые клетки посчитает одинаковыми, хотя обычные сравнения ведут себя с пустотой иначе. Это одно из немногих мест, где пустота ведёт себя предсказуемо.

И третье, менее очевидное: DISTINCT — не бесплатная операция. Чтобы убрать повторы, базе надо сравнить строки между собой, то есть отсортировать их или построить таблицу виденного. На пятнадцати строках это ничто, на десяти миллионах — заметная работа.

Отсюда привычка, которая отличает рабочий запрос от учебного: DISTINCT не ставят на всякий случай. Когда он появляется в запросе не потому, что нужны разные значения, а потому, что «строк как-то много и они задвоились», — это признак, что задвоил их не SELECT, а соединение таблиц. Лечить надо соединение, а DISTINCT только прячет симптом: уроку про размножение строк посвящён отдельный разговор.

Раз есть DISTINCT, должно быть и обратное — и оно есть: ALL. SELECT ALL city FROM customers означает «со всеми повторами», то есть ровно то, что происходит без единого слова. Пишут его редко, почти только в чужом коде и в учебниках, — но встретив, теперь знаете, что он ничего не меняет.

Второй вопрос возникает чуть позже и стоит того, чтобы ответить на него заранее: чем DISTINCT отличается от GROUP BY. Списком разных значений — ничем: SELECT DISTINCT city FROM customers и SELECT city FROM customers GROUP BY city дают одно и то же. Разница в том, что умеет второй: сгруппировав строки, он может ещё и посчитать по каждой группе — сколько покупателей в городе, какая там средняя цена.

Задания урока

Каждое проверяется сразу: ответ сверяется с эталоном, и на неверный вариант приходит разбор.

  1. Список колонок после SELECT влияет и на то, сколько строк вернёт запрос.легко
  2. Выведите название товара и цену с наценкой 20 %. Колонки: title и наценённая цена под именем price_up.средне
  3. Зачем колонке псевдоним?средне
  4. Выведите список городов, в которых живут покупатели, без повторов. Колонка: city.средне
Пройти урок с проверкой заданий Курс «SQL» открыт и бесплатен, прогресс сохраняется.
Открыть курс