SELECT: vi hämtar de data vi behöver

SELECT i detalj: vad vi hämtar och vad vi kallar det

22 min
What you'll learn
  • skriva minimala frågor SELECT kolumner FROM tabell och döpa kolumner med via AS
  • förklara en frågas logiska exekveringsordning: FROMWHERESELECTORDER BYLIMIT
  • åtgärda felet ”column does not exist” genom att upprepa uttrycket i stället för aliaset i WHERE
  • skilja på platser där aliaset redan syns (ORDER BY) och platser där det ännu inte finns (WHERE)

Kapitel 2 — ”Första behörigheten”

Inventeringen är läst — och QUERY håller sitt löfte. Mitt i salen vecklas en bärnstensfärgad holopanel ut med ett mjukt klick: lästerminalen öppnas under ditt konto. Markören blinkar på en tom rad. Arkivet är redo att svara — men det svarar bara på rätt ställda frågor. En fråga är ett behörighetsprotokoll: varje ord i den står exakt där det hör hemma.

QUERY: Terminalen är din. Tala kort och exakt med arkivet: det är inte dövt, det svarar bara inte på det otydliga.

Vad en läsfråga består av

Varje samtal med Kotomarkets arkiv börjar med en enkel fråga: vilka fält behöver du, och varifrån ska de hämtas. En minimal fråga svarar precis på det:

SELECT kolumner FROM tabell.

  • efter SELECT — listan med kolumner du vill ha, separerade med kommatecken (eller * för alla);
  • efter FROM — tabellen du läser från.

En kolumn i resultatet kan få ett mänskligt namn — ett via AS. Data ändras inte: du sätter bara en etikett på kolumnen så att utdata läses som en butikshylla i stället för en lagersedel från 2024.

En kadett framför en nyss öppnad lästerminal: två valda kolumner reser sig ur en holografisk tabell
Första behörigheten: lästerminalen är öppen. SELECT plockar bara ut de kolumner du behöver ur tabellen — och döper dem via 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 года.

Terminalen svarar: de första varorna på Kotomarkets hylla. Tekniska name och price är direkt döpta till läsbara kolumner.
Query result
товарцена
Беспроводные наушники5990.00
Смарт-часы8990.00
Портативная колонка3490.00
Веб-камера HD2790.00
Механическая клавиатура4590.00

Arkivet läser en fråga annorlunda än du skriver den

Du skriver en fråga uppifrån och ned: först SELECT, sedan FROM. Arkivet kör den i en annan — logisk — ordning:

FROMWHEREGROUP BYHAVINGSELECTORDER BYLIMIT

Först bestämmer databasen varifrån raderna ska hämtas, sedan filtrerar den dem, grupperar dem och filtrerar grupperna (GROUP BY och HAVING möter du i modul 3) — och först därefter beräknas själva SELECT-listan, inräknade. Sortering och beskärning av resultatet kommer sist.

Härifrån kommer klassikern som ställs på nästan varje intervju: ett alias från SELECT syns inte i WHERE — vid filtreringen finns det ännu inte:

-- Funkar inte: vid WHERE-steget finns aliaset sale_price ännu inte
SELECT name, price * 0.9 AS sale_price
FROM products
WHERE sale_price < 3000;   -- ERROR: column "sale_price" does not exist

-- Så här går det: vi upprepar uttrycket
SELECT name, price * 0.9 AS sale_price
FROM products
WHERE price * 0.9 < 3000;

Men ORDER BY sale_price fungerar: sorteringen körs efter SELECT, när aliaset redan finns. I PostgreSQL är ett alias dessutom tillåtet i GROUP BY (det är en utökning, inte standard), medan det i WHERE inte fungerar i något större .

Ordningen är strikt logisk: den beskriver frågans innebörd. Fysiskt är planeraren fri att kasta om stegen för snabbhetens skull, men resultatet måste stämma med den logiska ordningen.

we write: SELECT … FROM … WHERE …, but it runs like this:1 FROM2 WHERE3 GROUP BY4 HAVING5 SELECT6 ORDER BY7 LIMITthat is why a SELECT alias does not work in WHERE
Frågans logiska pipeline: du skriver den med SELECT först, men den körs med FROM först — aliasen föds först i SELECT-steget.
Interview question

Intervjufråga: i vilken ordning exekveras en SELECT-fråga logiskt, och varför kan ett från SELECT inte användas i WHERE men väl i ORDER BY?

Starkt svar: den logiska ordningen är FROMWHEREGROUP BYHAVINGSELECTORDER BYLIMIT. WHERE körs innan SELECT-listan beräknas, så aliasen finns ännu inte i det steget — uttrycket måste upprepas (eller flyttas in i en underfråga). ORDER BY körs efter SELECT, och där syns aliasen redan. Fysiskt får optimeraren kasta om stegen, men resultatet stämmer alltid med den logiska ordningen.

Check yourself
Varför behövs ett alias med AS i en fråga?

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

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

Например:

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;

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

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

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