SELECT: достаём нужные данные

Анатомия SELECT: что забираем и как называем

22 мин
Чему научишься
  • понимать, что SELECT формирует результат запроса, а не просто «достаёт колонки»
  • писать минимальные запросы вида SELECT столбцы FROM таблица
  • выводить не только столбцы таблицы, но и конкретные значения, текст, вычисления и выражения
  • подписывать колонки результата алиасами через AS
  • понимать разницу между настоящим именем столбца в таблице и временным именем в результате
  • объяснять логический порядок выполнения запроса: FROMWHEREGROUP BYHAVINGSELECTORDER BYLIMIT
  • чинить ошибку column does not exist, повторяя выражение вместо в WHERE
  • отличать места, где алиас уже виден (ORDER BY), от мест, где его ещё не существует (WHERE)

Глава 2 — «Первый допуск»

Опись прочитана — и КВЕРИ выполняет обещание.

В центре зала с мягким щелчком разворачивается янтарная голопанель: терминал чтения открывается под твою учётную запись. Курсор мигает в пустой строке. Архив готов отвечать — но отвечает он только на правильно заданные вопросы.

Запрос — это протокол допуска.
Каждое слово в нём стоит на своём месте.
Одно слово говорит, что показать. Другое — откуда взять. Третье — как назвать результат, чтобы человек понял его без расшифровки.

КВЕРИ: Терминал твой. Говори с архивом коротко и точно: он не глухой, он просто не отвечает на невнятное.

Курсант перед только что открывшимся терминалом чтения: из голографической таблицы поднимаются два выбранных столбца
Первый допуск: терминал чтения открыт. SELECT выхватывает из таблицы только нужные столбцы — и подписывает их через AS.

Что на самом деле делает SELECT

В SQL часто говорят:
SELECT «выбирает столбцы».

Это удобно для первого объяснения, но не совсем полно.

На самом деле SELECT формирует результат запроса.

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

SELECT может показать:

  • столбцы из таблицы;
  • конкретные числа;
  • текстовые значения;
  • результаты вычислений;
  • выражения на основе столбцов;
  • результаты функций;
  • временные названия колонок через .

То есть SELECT отвечает на вопрос:

Что должно оказаться в итоговой выдаче?

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

SELECT name, price
FROM products;

Этот запрос говорит:

Покажи из таблицы products значения столбцов name и price.

Но SELECT умеет больше. Например, в PostgreSQL можно выполнить запрос вообще без таблицы:

SELECT 1;

Результатом будет маленькая таблица из одной строки и одной колонки.

Можно вывести текст:

SELECT 'Котомаркет';

Можно вывести вычисление:

SELECT 2 + 2;

Можно сразу подписать результат понятным именем:

SELECT 2 + 2 AS result;

Такой запрос не «достаёт колонку из таблицы». Он просит базу вычислить выражение и показать его как результат.

Это важная мысль:

SELECT не всегда забирает готовые столбцы. Иногда он создаёт колонки результата прямо в момент выполнения запроса.


Минимальный запрос к таблице

Когда тебе нужны данные из таблицы, запрос обычно строится так:

SELECT столбцы
FROM таблица;

Например:

SELECT name, price
FROM products;

Разберём:

  • SELECT name, price — какие значения показать в результате;
  • FROM products — из какой таблицы брать строки;
  • ; — конец SQL-команды.

После SELECT перечисляют нужные столбцы через запятую:

SELECT name, price, stock
FROM products;

Этот запрос покажет три колонки результата:

  • name;
  • price;
  • stock.

А если нужно посмотреть все столбцы таблицы, можно использовать *:

SELECT *
FROM products;

Звёздочка означает:

Покажи все столбцы, которые есть в таблице.

Это удобно для первого знакомства с таблицей, но в рабочих запросах лучше не злоупотреблять *.

Почему?

Потому что SELECT * может вернуть лишние данные: технические поля, большие текстовые описания, служебные даты, внутренние идентификаторы. Кроме того, если структура таблицы изменится, результат SELECT * тоже изменится.

Для учебного исследования * — нормально.
Для аккуратного рабочего запроса лучше явно перечислять нужные столбцы.


Алиасы: как назвать колонку результата

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

Например, в таблице может быть столбец:

name

Но в результате отчёта хочется видеть:

товар

Для этого используют алиас — временное имя колонки в результате запроса.

SELECT name AS товар, price AS цена
FROM products;

AS можно читать как «назвать как»:

name AS товар

То есть:

Возьми значение из столбца name, но в результате подпиши эту колонку как товар.

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

Таблица products после такого запроса не меняется.
В ней как был столбец name, так он и остаётся.

Алиас — это не ремонт архива.
Это подпись на экране терминала.

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

Терминал отвечает: первые товары витрины «Котомаркета». Технические name и price сразу подписаны как человеческие колонки.

Архив читает запрос не так, как ты его пишешь

Ты пишешь запрос сверху вниз:

SELECT name AS товар, price AS цена
FROM products
LIMIT 5;

Но логически база начинает не с SELECT.

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

Поэтому логический порядок выполнения запроса такой:

FROMWHEREGROUP BYHAVINGSELECTORDER BYLIMIT

Сейчас тебе важны не все части этого конвейера. GROUP BY и HAVING встретятся позже, в модуле 3. Но общий порядок полезно увидеть уже сейчас.

Разберём смысл шагов:

  1. FROM
    База понимает, из какой таблицы брать данные.

  2. WHERE
    База отбирает только подходящие строки. Этот шаг появится в следующем уроке.

  3. GROUP BY
    База собирает строки в группы. Это тема будущего модуля.

  4. HAVING
    База фильтрует уже не отдельные строки, а группы.

  5. SELECT
    База формирует итоговые колонки результата: берёт столбцы, считает выражения, назначает .

  6. ORDER BY
    База сортирует результат.

  7. LIMIT
    База оставляет нужное количество строк.

Из этого порядка следует важное правило:

Алиас рождается только на шаге SELECT.

А значит, до шага SELECT алиаса ещё не существует.

Именно поэтому алиас из SELECT нельзя использовать в WHERE.

-- Так нельзя: на шаге WHERE алиаса sale_price ещё нет
SELECT name, price * 0.9 AS sale_price
FROM products
WHERE sale_price < 3000;

База попытается выполнить WHERE раньше, чем создаст колонку результата sale_price.

Поэтому она увидит:

WHERE sale_price < 3000

и не поймёт, что такое sale_price.

В PostgreSQL такая ошибка обычно выглядит так:

ERROR: column "sale_price" does not exist

Правильный вариант — повторить выражение:

SELECT name, price * 0.9 AS sale_price
FROM products
WHERE price * 0.9 < 3000;

Здесь база может выполнить фильтрацию, потому что price — настоящий столбец таблицы products. Он уже доступен на этапе WHERE.

А вот в ORDER BY алиас использовать можно:

SELECT name, price * 0.9 AS sale_price
FROM products
ORDER BY sale_price;

Почему это работает?

Потому что ORDER BY логически выполняется после SELECT.
К этому моменту алиас sale_price уже создан.

Важно: этот порядок называется логическим. Он объясняет смысл запроса и правила видимости имён. Физически базы данных может переставлять операции ради скорости, но итоговый результат обязан соответствовать логическому порядку.

пишем: SELECT … FROM … WHERE …, а выполняется так:1 FROM2 WHERE3 GROUP BY4 HAVING5 SELECT6 ORDER BY7 LIMITпоэтому алиас из SELECT не работает в WHERE
Логический конвейер запроса: пишется он с SELECT, а выполняется с FROM — алиасы рождаются только на шаге SELECT.
Вопрос с собеседования

Вопрос с собеседования:
в каком порядке логически выполняется SELECT-запрос и почему из SELECT нельзя использовать в WHERE, а в ORDER BY — можно?

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

FROMWHEREGROUP BYHAVINGSELECTORDER BYLIMIT.

WHERE выполняется до вычисления списка SELECT, поэтому алиасов на этом шаге ещё не существует. Если нужно отфильтровать по вычислению, выражение приходится повторить:

SELECT name, price * 0.9 AS sale_price
FROM products
WHERE price * 0.9 < 3000;

А ORDER BY выполняется после SELECT, поэтому алиас там уже виден:

SELECT name, price * 0.9 AS sale_price
FROM products
ORDER BY sale_price;

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

Проверь себя
Зачем в запросе нужен алиас AS?

Результат запроса — тоже таблица

Когда ты выполняешь запрос, база возвращает результат в виде таблицы.

Например:

SELECT name AS товар, price AS цена
FROM products
LIMIT 5;

может вернуть:

товарцена
Нейроошейник «Мур-7»4200
Автокормушка «Орбита»3100
Лазерная мышь тренировочная900
Капсула сна для кота12500
Переноска антигравитационная7800

Эта таблица результата не обязана полностью повторять таблицу products.

В таблице products могут быть десятки столбцов:

  • id;
  • name;
  • category;
  • price;
  • stock;
  • created_at;
  • updated_at;
  • и другие.

Но в результате ты попросил только две колонки:

SELECT name AS товар, price AS цена

Поэтому терминал показывает только их.

Запрос — это не сама таблица.
Запрос — это инструкция, по которой база собирает временную выдачу.

SELECT без таблицы

В большинстве учебных примеров SELECT используется вместе с FROM:

SELECT name
FROM products;

Но в PostgreSQL SELECT может работать и без таблицы.

Например:

SELECT 1;

База вернёт одну строку с числом 1.

Можно вывести текст:

SELECT 'Архив активен';

Можно выполнить вычисление:

SELECT 10 * 3;

Можно дать результату понятное имя:

SELECT 10 * 3 AS total;

Результат будет выглядеть примерно так:

total
30

Зачем это нужно?

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

Иногда эти колонки берутся из таблицы.
Иногда вычисляются прямо в запросе.

КВЕРИ: Архив не обязан открывать ящик, чтобы ответить на вопрос. Иногда ответ уже содержится в самом запросе.

Примечание: в этом курсе мы ориентируемся на PostgreSQL. В некоторых других синтаксис для запроса без обычной таблицы может отличаться.

Выражения в SELECT

В SELECT можно писать не только имена столбцов, но и выражения.

Например, в таблице products есть цена товара:

price

Если нужно показать цену со скидкой 10%, можно написать:

SELECT name, price, price * 0.9 AS sale_price
FROM products;

Здесь:

  • name — обычный столбец;
  • price — обычный столбец;
  • price * 0.9 — вычисление;
  • AS sale_price — имя для вычисленной колонки в результате.

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

Если в таблице есть такие данные:

nameprice
Нейроошейник «Мур-7»4200
Лазерная мышь тренировочная900

то запрос:

SELECT name, price, price * 0.9 AS sale_price
FROM products;

вернёт примерно:

namepricesale_price
Нейроошейник «Мур-7»42003780
Лазерная мышь тренировочная900810

Важный момент: колонка sale_price не появилась в таблице products.

Она появилась только в результате запроса.

То есть SELECT может создавать вычисляемые колонки результата.

AS: временная подпись, а не изменение таблицы

Алиас через AS можно дать:

  • обычному столбцу;
  • вычисленному выражению;
  • текстовому значению;
  • результату функции.

Примеры:

SELECT name AS product_name
FROM products;
SELECT price * 0.9 AS sale_price
FROM products;
SELECT 'Котомаркет' AS archive_name;

AS делает результат понятнее.

Сравни:

SELECT price * 0.9
FROM products;

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

Лучше:

SELECT price * 0.9 AS sale_price
FROM products;

Теперь сразу ясно, что это цена со скидкой.

Иногда AS можно не писать:

SELECT name product_name
FROM products;

Но для новичков и для читаемого учебного кода лучше использовать AS явно:

SELECT name AS product_name
FROM products;

Так запрос легче читать.


Алиасы из нескольких слов

Если хочешь назвать колонку несколькими словами, нужны двойные кавычки:

SELECT price * 0.9 AS "цена со скидкой"
FROM products;

Но в учебных и рабочих запросах обычно удобнее использовать короткие имена без пробелов:

SELECT price * 0.9 AS sale_price
FROM products;

Такой проще использовать дальше в ORDER BY и легче читать в коде.

Важно не путать:

  • одинарные кавычки '...' — для текста;
  • двойные кавычки "..." — для имён столбцов, алиасов и других идентификаторов, если они содержат пробелы или требуют точного написания.

Пример текста:

SELECT 'цена со скидкой' AS label;

Пример имени колонки результата:

SELECT price * 0.9 AS "цена со скидкой"
FROM products;

SELECT *: быстро посмотреть всё

Звёздочка * означает «все столбцы».

SELECT *
FROM products;

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

Но SELECT * — это грубый прожектор.
Он освещает всё сразу: нужное, лишнее, служебное, временное, техническое.

В учебных запросах он помогает быстро сориентироваться.
В рабочих запросах лучше писать явно:

SELECT name, price, stock
FROM products;

Так ты точно контролируешь результат.

Плохая привычка новичка:

SELECT *
FROM products;

даже когда нужны только название и цена.

Хорошая привычка:

SELECT name, price
FROM products;

Такой запрос понятнее, аккуратнее и безопаснее для будущих изменений.

Разбор первого рабочего запроса

Посмотрим на запрос из терминала:

SELECT name AS товар, price AS цена
FROM products
LIMIT 5;

Он читается так:

Из таблицы products покажи значения столбцов name и price,
но в результате подпиши их как товар и цена,
и выведи только первые 5 строк.

Разбор по строкам:

SELECT name AS товар, price AS цена

Формирует колонки результата.

FROM products

Указывает, из какой таблицы брать данные.

LIMIT 5

Ограничивает выдачу пятью строками.

LIMIT полезен, когда таблица большая. Если в архиве тысячи или миллионы товаров, не всегда нужно выводить всё сразу. Иногда достаточно первых нескольких строк, чтобы проверить структуру данных.

КВЕРИ: Не открывай весь шлюз, если хочешь проверить давление. Пяти строк достаточно, чтобы понять, отвечает ли архив правильно.

Ошибка новичка: использовать слишком рано.

Такой запрос выглядит логично для человека:

SELECT name, price * 0.9 AS sale_price
FROM products
WHERE sale_price < 3000;

Но для базы он неверный.

На момент выполнения WHERE алиаса sale_price ещё нет. Он появится позже, на шаге SELECT.

Правильно:

SELECT name, price * 0.9 AS sale_price
FROM products
WHERE price * 0.9 < 3000;

Или, если выражение большое и не хочется повторять его, позже можно будет использовать . Но это тема следующих модулей.

Где алиас виден, а где нет

Главное правило:

Алиас виден только после того, как он создан на шаге SELECT.

Поэтому:

Часть запросаМожно использовать из SELECT?Почему
WHEREНетWHERE выполняется раньше SELECT
SELECTАлиас создаётся здесьНа этом шаге появляется имя результата
ORDER BYДаORDER BY выполняется после SELECT
LIMITНе относится к алиасамОн просто ограничивает количество строк

Пример, где алиас не работает:

SELECT name, price * 0.9 AS sale_price
FROM products
WHERE sale_price < 3000;

Пример, где алиас работает:

SELECT name, price * 0.9 AS sale_price
FROM products
ORDER BY sale_price;

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

Частые ошибки в первых SELECT-запросах

Ошибка 1. Забыть запятую между столбцами

Неправильно:

SELECT name price
FROM products;

База может понять это не так, как ты ожидаешь: как будто price — это для name.

Правильно:

SELECT name, price
FROM products;

Ошибка 2. Поставить FROM раньше SELECT

Неправильно:

FROM products
SELECT name, price;

Правильно:

SELECT name, price
FROM products;

SQL пишется в своём синтаксическом порядке: сначала SELECT, потом FROM.

Но логически база начинает обработку с FROM.


Ошибка 3. Думать, что алиас меняет таблицу

SELECT name AS товар
FROM products;

После этого в таблице не появляется столбец товар.

Алиас существует только в результате этого запроса.


Ошибка 4. Использовать одинарные кавычки для имени алиаса

Лучше не писать так:

SELECT price AS 'цена'
FROM products;

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

Правильно:

SELECT price AS цена
FROM products;

Или, если нужен алиас с пробелом:

SELECT price AS "цена товара"
FROM products;

Ошибка 5. Использовать алиас в WHERE

Неправильно:

SELECT price * 0.9 AS sale_price
FROM products
WHERE sale_price < 3000;

Правильно:

SELECT price * 0.9 AS sale_price
FROM products
WHERE price * 0.9 < 3000;

Ошибка 6. Всегда писать SELECT *

Для первого знакомства с таблицей можно:

SELECT *
FROM products;

Но для понятного запроса лучше:

SELECT name, price
FROM products;

Так сразу видно, какие данные нужны.

Проверь себя
Что формирует SELECT?
Проверь себя
Почему такой запрос может вызвать ошибку?
SELECT name, price * 0.9 AS sale_price
FROM products
WHERE sale_price < 3000;
Проверь себя
Что вернёт запрос в PostgreSQL?
SELECT 2 + 2 AS result;

КВЕРИ: Первый допуск получен. Ты больше не смотришь на архив как на стену данных. Ты умеешь задавать ему форму ответа.