SELECT: precies de juiste data ophalen

Mastercheck: SELECT in actie

22 min
What you'll learn
  • je oefent het samenstellen van een volledige SELECT: kolommen kiezen, aliassen gebruiken, WHERE-filters schrijven, BETWEEN/IN/LIKE toepassen en sorteren met LIMIT — aan de hand van oefenopgaven
  • je bewijst dat je de oorzaken van «stille» fouten kunt vinden: vergelijkingen met NULL, OR zonder haakjes, CASE zonder ELSE, LIMIT zonder ORDER BY
  • je ontwikkelt betrouwbare querygewoonten: haakjes in gemengde voorwaarden, een expliciete ELSE, sorteren met een unieke sleutel

Laten we SELECT oefenen met echte opgaven

QUERY dooft de overbodige panelen. In de zaal blijven één terminal en drie opgaven over: het examen voor de eerste toegang. De Academie gelooft niet in woorden, alleen in queries.

Je hebt de basisuitrusting van de lezer-archivaris samengesteld: je kiest de kolommen die je nodig hebt, geeft ze begrijpelijke aliassen, filtert rijen met WHERE, gaat zorgvuldig om met NULL, gebruikt BETWEEN/IN/LIKE, bepaalt de volgorde met ORDER BY/LIMIT, verwijdert dubbele rijen met DISTINCT en voegt eenvoudige logica toe met CASE.

Maak het nu concreet met de opgaven uit de trainer. Ze lijken op gewone vragen aan «Kotomarket»: wat moet er zichtbaar zijn, wat moet eruit worden gefilterd en welk label krijgt het resultaat. Los ze op in de editor (ze openen in een nieuw tabblad), dan wordt het blok hieronder gemarkeerd als afgerond.

Een halfdonkere zaal met één terminal, drie opgaven en een vergrendeld, versleuteld datablok dat diep in het hologram flikkert
Het examen voor de eerste toegang: drie queries tussen jou en het volgende niveau van het archief.

Как читать полный SELECT

Когда запрос становится длиннее трёх строк, новичок часто теряется. Кажется, что SQL выполняется строго сверху вниз, как текст.

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

Например:

SELECT
    name,
    category,
    price,
    CASE
      WHEN price < 1500 THEN 'дешёвый'
      WHEN price < 4000 THEN 'средний'
      ELSE 'дорогой'
    END AS segment
FROM products
WHERE category IN ('Книги', 'Игрушки')
  AND price BETWEEN 1000 AND 3000
ORDER BY price DESC, id
LIMIT 5;

Такой запрос можно разобрать по шагам.

Сначала источник:

FROM products

База берёт таблицу товаров.

Потом фильтр строк:

WHERE category IN ('Книги', 'Игрушки')
  AND price BETWEEN 1000 AND 3000

Остаются только книги и игрушки с ценой от 1000 до 3000 включительно.

Потом список столбцов и вычислений:

SELECT
    name,
    category,
    price,
    CASE ... END AS segment

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

Потом порядок:

ORDER BY price DESC, id

Сначала дорогие товары, а при одинаковой цене — стабильная сортировка по id.

И только после этого ограничение:

LIMIT 5

Остаются первые пять строк уже после сортировки.

Главная мысль:

LIMIT не выбирает «лучшие» строки сам. Он просто берёт верхушку того порядка, который ты задал через ORDER BY.

Что делает запрос надёжным

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

Надёжный запрос обычно обладает тремя признаками.

Первый признак — он явно говорит, какие строки нужны.

Плохо, когда условие приходится угадывать по куску логики. Хорошо, когда WHERE читается как точное правило:

WHERE category IN ('Книги', 'Игрушки')
  AND price BETWEEN 1000 AND 3000

Второй признак — он явно говорит, в каком порядке нужен результат.

Если важны самые дорогие товары, самые свежие заказы или первые пользователи по алфавиту, это должно быть записано в ORDER BY:

ORDER BY price DESC, id

Третий признак — он не прячет неопределённость.

Если в данных может быть NULL, запрос должен учитывать это явно:

WHERE city IS NULL

или:

WHERE city <> 'Москва'
   OR city IS NULL

Если в CASE есть строки, которые не попали ни в одну ветку, лучше заранее решить, что с ними делать:

ELSE 'другой статус'

Если порядок при равных значениях важен, его нужно добить уникальным ключом:

ORDER BY price DESC, id

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

Тихие ошибки: когда запрос работает, но врёт

Самые неприятные ошибки в SQL не всегда выглядят как красная ошибка синтаксиса.

Гораздо чаще запрос запускается, возвращает таблицу, но строки в ней не те.

Например, сравнение с NULL:

WHERE city = NULL

Синтаксически запрос может быть корректным, но он не найдёт строки, где города нет. Для NULL нужна проверка:

WHERE city IS NULL

Или условие со смешанными AND и OR:

WHERE category = 'Книги'
   OR category = 'Игрушки'
  AND price < 3000

Такой запрос читается глазами как:

книги или игрушки, и цена меньше 3000

Но SQL сначала связывает AND, а потом OR. Поэтому фактическая логика другая:

WHERE category = 'Книги'
   OR (category = 'Игрушки' AND price < 3000)

Если тебе нужно применить цену к обеим категориям, нужны скобки:

WHERE (category = 'Книги' OR category = 'Игрушки')
  AND price < 3000

Или так, ещё чище:

WHERE category IN ('Книги', 'Игрушки')
  AND price < 3000

Ещё один тихий сбой — CASE без ELSE:

CASE
  WHEN status = 'paid' THEN 'оплачен'
  WHEN status = 'pending' THEN 'ожидает'
END AS status_label

Если появится статус cancelled, метка станет NULL. Иногда это нормально, но чаще для отчёта лучше явно написать запасной вариант:

ELSE 'другой статус'

И наконец, LIMIT без ORDER BY:

SELECT name, price
FROM products
LIMIT 5;

Этот запрос не выбирает топ-5. Он выбирает любые первые пять строк в том порядке, который база решила вернуть сейчас.

Для топа нужен критерий:

SELECT name, price
FROM products
ORDER BY price DESC, id
LIMIT 5;

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

КВЕРИ: Архив не читает намерения. Он читает запрос. Если мысль не записана явно, её не существует.

Перед отправкой запроса

Перед тем как отправить решение в тренажёре, полезно быстро пройтись по запросу глазами.

Сначала проверь, что ты выбрал ровно нужные столбцы.

Если в задаче просят:

name, price

не нужно оставлять:

SELECT *

Даже если так проще во время черновика, финальный ответ должен показывать то, что просит задача.

Потом проверь фильтр.

Если в условии задачи есть «от 1000 до 3000 включительно», хорошо подходит:

BETWEEN 1000 AND 3000

Если сказано «категория Книги или Игрушки», читаемее использовать:

IN ('Книги', 'Игрушки')

Если нужно «начинается с», подойдёт:

LIKE 'К%'

Если нужно «содержит», подойдёт:

LIKE '%К%'

Но помни: ведущий % может быть дорогим на больших таблицах.

Потом проверь NULL.

Если нужно найти отсутствующее значение, не пиши:

= NULL

Пиши:

IS NULL

Если нужно исключить значение, но сохранить строки с NULL, добавь это явно:

WHERE city <> 'Москва'
   OR city IS NULL

Потом проверь сортировку.

Если в задаче есть слова:

самые дорогие
самые дешёвые
последние
первые
топ

почти наверняка нужен ORDER BY.

Если есть ограничение количества строк, почти наверняка нужен LIMIT.

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

ORDER BY price DESC, id

Так результат будет стабильным.

Что ты уже умеешь к концу модуля

Этот модуль был про чтение строк.

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

Тебе доступен базовый маршрут:

SELECT ...
FROM ...
WHERE ...
ORDER BY ...
LIMIT ...

Ты понимаешь, зачем нужны :

price * stock AS stock_value

Ты умеешь работать с отсутствующими значениями:

IS NULL
IS NOT NULL
COALESCE(...)

Ты умеешь задавать короткие фильтры:

BETWEEN
IN
LIKE

Ты умеешь получать словарь значений:

SELECT DISTINCT status
FROM orders;

Ты умеешь добавлять в выдачу человеческие метки:

CASE
  WHEN ... THEN ...
  ELSE ...
END

И главное — ты уже знаешь, что корректный синтаксис не гарантирует корректную мысль.

SQL может выполнить запрос идеально и всё равно вернуть не то, что ты хотел, если условие записано неточно.

Interview question

Sollicitatievraag: de query is syntactisch correct, maar rijen verdwijnen «ongemerkt» uit de uitvoer of krijgen verkeerde waarden. Noem de typische oorzaken.

Sterk antwoord: op dit niveau zijn er vier klassieke oorzaken. (1) Vergelijkingen met NULL: =, <> en NOT IN met een lijst waarin een zit, geven — de rij komt niet door WHERE; je lost dit op met IS NULL, IS DISTINCT FROM, COALESCE. (2) OR zonder haakjes: AND bindt sterker, waardoor de voorwaarde anders wordt gegroepeerd dan ze leest. (3) CASE zonder ELSE geeft NULL terug voor niet-gedekte rijen, en WHEN NULL in de eenvoudige vorm is dood. (4) LIMIT zonder ORDER BY geeft «willekeurige» rijen terug: de volgorde zonder sortering is niet gegarandeerd. In een sollicitatiegesprek gaat het niet om het opdreunen van de lijst, maar om de gewoonte: haakjes in gemengde voorwaarden, een expliciete ELSE, expliciet sorteren met een unieke sleutel.

QUERY: From here the archive opens only to those who count. Revenue, average order value, groups — the next level of clearance.