← Все курсы · Курс SQL · Все руководства

Основы SQL, от начала до конца

Каждая основная идея SQL в том порядке, в котором они дополняют друг друга · Написаны для прослушивания · Часть Analyst Prep Kit

К , аналитик данных · Обновлено

К концу этой страницы вы сможете сказать вслух и своими словами, что делает каждая основная часть SQL. Что на самом деле представляют собой таблица и строка. Шесть предложений и порядок, в котором они на самом деле выполняются, а не тот порядок, в котором вы их вводите. NULLи почему это нарушает сравнения. Фильтрация, агрегирование, GROUP BY и HAVING. Присоединяется. CASE. Подзапросы, CTE и оконные функции. Ключи и индексы. Этот список — это большая часть того, что от вас потребуют на работе аналитика, на собеседовании и на первом реальном наборе данных.

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

Краткая версия: SQL — это одно предложение, состоящее из шести частей, каждая часть отвечает на отдельный вопрос о ваших строках. Узнайте, что делает каждая часть и где она работает, а остальное — словарный запас.

Одна идея в большей степени определяет ваш опыт работы с SQL, чем любая другая, поэтому она дает представление о картине. Вы пишете запрос в одном порядке. База данных запускает его в другом порядке. Почти каждая сбивающая с толку ошибка SQL является этим пробелом.

You write a query in one order and it runs in another Two columns of stacked boxes face each other. The left column, headed "you write", lists the clauses in typing order from top to bottom: SELECT, FROM, WHERE, GROUP BY, HAVING, ORDER BY, LIMIT. The right column, headed "it runs", lists the same clauses in execution order: FROM, WHERE, GROUP BY, HAVING, SELECT, ORDER BY, LIMIT. Curved lines connect each clause on the left to the same clause on the right. Six of the seven lines run roughly straight across. One line, the one belonging to SELECT, is drawn in a strong accent color and sweeps steeply downward from the very top of the left column to the fifth position on the right, showing that SELECT is written first but runs almost last, after grouping has already happened. you write it runs SELECT FROM WHERE GROUP BY HAVING ORDER BY LIMIT FROM WHERE GROUP BY HAVING SELECT ORDER BY LIMIT
Предложение, которое вы вводите первым, выполняется почти последним.
Что вы узнаете
  1. Таблицы, строки и одно слово, которое предотвращает большинство ошибок
  2. Шесть пунктов и порядок их выполнения
  3. Фильтрация и что с ней делает NULL
  4. Агрегация, ГРУППИРОВКА ПО и ИМЕЮЩАЯ
  5. Объединение двух таблиц
  6. Формирование вывода: DISTINCT, ORDER BY, CASE, псевдонимы.
  7. Подзапросы, CTE и оконные функции
  8. Ключи, индексы и что означает реляционный характер
  9. Как это изучить, чтобы это прижилось
  10. Все на одном экране
Что это за страница, а что нет. Это концептуальный уровень: что представляет собой каждая часть и что она делает. Это не курсы набора текста. Если вам нужны повторения, сопутствующее упражнение предоставит вам тринадцать работоспособных запросов, каждый из которых добавляет что-то к последнему. Пройти этот один раз вместе с этим один раз — самый быстрый путь через оба.

1. Таблицы, строки и одно слово, которое предотвращает большинство ошибок.

Перед пояснением: две таблицы содержат по 500 строк. Означает ли это, что они содержат одинаковое количество информации об одних и тех же вещах?

A Таблица представляет собой сетку. Столбцы — это поля, и каждое значение в столбце — это одно и то же. Строки — это записи. А база данных представляет собой набор таблиц, которые знают друг о друге.

Теперь слово, которое предотвращает большинство ошибок SQL: grain. Уровень детализации таблицы — это то, что означает одна строка. Скажите это как предложение, начинающееся с «одна строка на».

Все эти три таблицы могут иметь по 500 строк и означать совершенно разные вещи. Уровень детализации — это ответ на вопрос «что я считаю», и каждый счет, сумма и среднее значение, которые вы пишете, — это ответ на какое-то уровень детализации. Если число оказывается неправильным, оно обычно оказывается верным в той степени, которую вы не предполагали.

Еще одна вещь, которую нужно знать о таблице, прежде чем запрашивать ее, — это ее Типы данных. В широком смысле: целые числа, десятичные числа, текст, даты и логические значения. Виды не являются украшением. Дата, сохраненная в виде текста, будет отсортирована в алфавитном порядке, поэтому первое декабря будет предшествовать второму января. Число, сохраненное в виде текста, не будет корректно сравниваться или складываться. Если что-то очевидное отказывается работать, сначала проверьте тип.

2. Шесть пунктов и порядок их выполнения

Перед пояснением: вы называете столбец revenue в твоем SELECT, затем попробуйте отфильтровать revenue в твоем WHERE, а в базе данных указано, что такого столбца нет. Это прямо здесь, на строке выше. Почему база данных его не видит?

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

SELECT   region, COUNT(*) AS orders
FROM     orders
WHERE    order_date >= '2026-01-01'
GROUP BY region
HAVING   COUNT(*) > 100
ORDER BY orders DESC
LIMIT    10;

Прочтите в порядке ввода: покажите мне эти вещи, отсюда, где это правда, сгруппированы вот так, оставьте только такие группы, отсортированы вот так и остановитесь после десяти.

Но база данных не запускает его в таком порядке. Он работает FROM, затем WHERE, затем GROUP BY, затем HAVING, затем SELECT, затем ORDER BY, затем LIMIT. Именно такой порядок показан на картинке выше, и он объясняет три вещи, которые люди иначе запоминают как произвольные правила.

Первое – это ваш вопрос. WHERE бежит раньше SELECT, так что на данный момент WHERE оценивается псевдоним revenue еще не существует. Вот почему вам придется повторить все выражение в WHEREили оберните запрос в другой.

Второй WHERE против HAVING, который является самым часто задаваемым вопросом на собеседовании по SQL после присоединения. WHERE запускается перед группировкой, поэтому фильтрует отдельные строки. HAVING запускается после группировки, поэтому он фильтрует группы и является единственным, кто может видеть агрегат типа COUNT(*). «Заказы на сумму более 500 долларов» — это WHERE. «Регионы с более чем 100 заказами» — это HAVING.

Третий заключается в том, что ORDER BY бежит за SELECT, вот почему это может используйте свой псевдоним. ORDER BY orders DESC работает в приведенном выше запросе с именем, которое WHERE не мог видеть. Тот же запрос, тот же псевдоним, другой ответ исключительно из-за того, когда выполняется каждое предложение.

Прежде чем читать дальше, скажите это вслух: почему можно ORDER BY используйте псевдоним, который WHERE не может?

3. Фильтрация и что с ней делает NULL

Перед пояснением: в таблице 100 строк. Вы запускаете один фильтр и получаете 60 строк, затем запускаете противоположный фильтр и получаете 30. Где остальные 10?

WHERE сохраняет строки, которые делают условие истинным. Строительные блоки небольшие.

ОператорЧто он делает
= <> < > <= >=Сравните одно значение с другим
AND OR NOTОбъедините условия. AND применяется до OR, поэтому используйте скобки, когда смешиваете их.
IN (a, b, c)Соответствует любому значению в списке. короче, чем цепочка OR.
BETWEEN x AND yДиапазон, и оба конца включены
LIKE 'north%'Текстовый узор. % означает любую серию символов, _ означает ровно один.
IS NULL / IS NOT NULLЕдинственный правильный способ проверить пропущенное значение

Это подводит нас к ответу на предварительный вопрос. NULL не означает ноль и не означает пустой текст. Это значит неизвестно. И сравнение с неизвестным не оказывается ложным, оно возвращает неизвестное, что является третьим состоянием. Строка, значение которой неизвестно, не проходит оба region = 'North' и region <> 'North', потому что SQL не может сказать, что ни одно из них истинно. Этих десяти строк нет ни в одном результате.

Вот почему = NULL никогда не работает и IS NULL это отдельная часть синтаксиса. Вот почему NOT IN против списка, содержащего NULL вообще ничего не возвращает, что в первый раз становится действительно неприятным днем.

Повседневная привычка, которая вас спасает: всякий раз, когда вы пишете фильтр, исключающий что-то, спрашивайте, что происходит со строками, где столбец неизвестен, и решайте специально. Часто вы хотите WHERE region <> 'North' OR region IS NULL.

4. Агрегация, группировка и наличие

Перед объяснением: COUNT(*) и COUNT(customer_id) в одной и той же таблице могут возвращаться разные числа. В чем разница между тем, что задают эти два вопроса?

Ан агрегатная функция принимает много строк и возвращает одно значение. Есть пять, которые вы будете использовать постоянно: COUNT, SUM, AVG, MIN, MAX.

GROUP BY решает, что означает «много строк». Без него агрегат сворачивает всю таблицу в одну строку. С GROUP BY region, он сжимается до одной строки на регион, и внутри каждого из них вычисляется агрегат. Это та же идея, что и уровень детализации вида в Tableau, и если вы сталкивались с этим, то это точно такая же механика в другой одежде. Прохождение этого есть в Руководство по концепциям Tableau.

Следующее правило: каждый столбец в вашем SELECT должно быть либо в GROUP BY или быть обернутым в совокупность. Третьего варианта нет, потому что нет разумного ответа на вопрос «дайте мне имя клиента для этой группы из 400 клиентов».

Теперь на счет три, это и есть предварительный вопрос.

Написано какимеет значение
COUNT(*)Ряды. Каждый ряд, включая полные NULL.
COUNT(customer_id)Строки, в которых нет этого столбца NULL. Отсутствующие значения пропускаются.
COUNT(DISTINCT customer_id)Сколько разных клиентов, независимо от того, сколько строк каждый занимает.

Это три совершенно разных вопроса: сколько строк, сколько строк содержат это и сколько различных вещей. Разрыв между первой и третьей — это самый быстрый способ обнаружить повторяющиеся строки, поэтому он возвращается в руководство по соединениям.

AVG Пропускает NULL тоже, что имеет большее значение, чем кажется. Если 40 из 100 строк не имеют значения, AVG делится на 60, а не на 100. Если пропущенное значение действительно означает ноль, сначала замените его на COALESCE(column, 0), который возвращает первый объект в своем списке, который не является NULL.

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

5. Объединение двух таблиц

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

A Объединение таблиц (JOIN) объединяет две таблицы путем сопоставления строк по общему значению, называемому ключом. Механика — это одно предложение, и его стоит придерживаться: для каждой строки слева база данных находит каждую строку справа, ключ которой совпадает, и записывает по одной выходной строке на каждую пару.

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

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

Типы, кратко. INNER JOIN сохраняет только совпадающие пары. LEFT JOIN сохраняет каждую строку из левой таблицы, заполняя правую часть NULL где ничего не совпало. RIGHT JOIN делает то же самое наоборот. FULL OUTER JOIN сохраняет несовпадающие строки с обеих сторон. CROSS JOIN сочетает все со всем и почти никогда не бывает тем, что вы хотите случайно.

В соединениях возникает наибольшая доля реальных ошибок аналитиков, и оба режима сбоя невидимы в тексте запроса и очевидны при подсчете строк. Это целое руководство: как объединить две таблицы, не теряя и не удваивая строки работает с обоими на 41 миллионе реальных строк, с двумя счетчиками, которые перехватывают каждую из них.

6. Формирование вывода: DISTINCT, ORDER BY, CASE, псевдонимы.

Перед пояснением: в вашем результате один и тот же клиент указан девять раз. Является DISTINCT исправление или это способ скрыть вопрос, который вам следует задать?

DISTINCT удаляет повторяющиеся строки из результата. Это полезно для настоящего вопроса, например «какие регионы указаны в этой таблице». Это опасно как рефлекс, поскольку повторяющиеся строки обычно означают, что соединение умножило ваши данные, и удаление их вручную скрывает это, а не исправляет. Сначала спросите, откуда взялись дубликаты, а затем принимайте решение.

ORDER BY сорта. По возрастанию по умолчанию, DESC по убыванию, и вы можете сортировать по нескольким столбцам в порядке приоритета. LIMIT занимает первые н строк и является вашим лучшим другом на столе, который вы никогда раньше не открывали, потому что SELECT * FROM big_table LIMIT 10 покажет вам, с чем вы имеете дело, за секунду.

псевдонимы переименовывать вещи. AS avg_hours называет выходной столбец и FROM customers AS c называет таблицу, чтобы вы могли писать c.name. Двум объединенным таблицам почти всегда нужны эти псевдонимы, поскольку обе могут содержать столбец с одинаковым именем. Вся привычка заключена в Псевдонимы SQL и чтение запроса вслух.

CASE — это оператор «если-то» SQL, который преобразует столбец в категории.

SELECT name,
       CASE WHEN tenure_months < 12 THEN 'First year'
            WHEN tenure_months < 36 THEN 'Established'
            ELSE 'Loyal'
       END AS segment
FROM customers;

Он читает сверху вниз и останавливается на первом совпадении, поэтому для каждого из приведенных выше диапазонов не требуется верхняя граница. Все, что не соответствует, попадает в ELSE, и без ELSE это становится NULL. CASE также работает внутри агрегата, то есть подсчета подмножества в том же запросе: SUM(CASE WHEN churned = 1 THEN 1 ELSE 0 END).

7. Подзапросы, CTE и оконные функции

Прежде чем объяснить: вам нужно сравнить расходы каждого клиента со средними показателями по его региону. Для этого нужны две разные группы в одном результате. Как один запрос может иметь два зерна одновременно?

Три инструмента, и это шаг от написания запросов к их структурированию.

A подзапрос это запрос внутри другого запроса. Он может сидеть в FROM, где он действует как временная таблица, или в WHERE, где он предоставляет значение или список для сравнения.

A CTE, обычное табличное выражение, представляет собой ту же идею, написанную так, чтобы человек мог ее прочитать. Вы заранее называете результат с помощью WITH, затем используйте это имя ниже.

WITH regional AS (
  SELECT region, AVG(spend) AS region_avg
  FROM customers
  GROUP BY region
)
SELECT c.name, c.spend, r.region_avg
FROM customers AS c
JOIN regional AS r ON c.region = r.region;

Это ответ на предварительный вопрос, сделанный явным образом. Вычислите ответ на уровне региона один раз, присвойте ему имя, а затем соедините его со строками на уровне клиента. Чтение сверху вниз происходит в том же порядке, в котором выполняется работа, поэтому CTE стоит использовать, даже если подойдет вложенный подзапрос. Запрос, которому может следовать кто-то другой, — это запрос, которому кто-то другой будет доверять.

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

SELECT name, spend,
       AVG(spend) OVER (PARTITION BY region) AS region_avg
FROM customers;

В этом вся идея: OVER говорит: «Посмотрите в окно рядов», и PARTITION BY говорит, какие строки принадлежат одному и тому же окну. Обычный GROUP BY сворачивает ваши строки. Оконная функция выполняет ту же самую математику и сохраняет их. Другие распространенные из них: ROW_NUMBER, RANK и DENSE_RANK для нумерации строк внутри каждой группы и LAG и LEAD для достижения предыдущей или следующей строки, именно так вы рассчитываете ежемесячные изменения.

8. Ключи, индексы и что означает реляционный характер

Прежде чем объяснить: почему адрес одного и того же клиента хранится в одной таблице, а не повторяется в каждом его заказе?

A первичный ключ столбец, который однозначно идентифицирует строку. Один идентификатор клиента, один клиент, никогда не повторяется, никогда NULL. А внешний ключ тот же самый идентификатор появляется в другой таблице, чтобы указать назад, поэтому заказ содержит идентификатор клиента того, кто его разместил.

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

Ан индекс — это структура поиска, которую база данных хранит в столбце, поэтому ей не нужно читать каждую строку, чтобы найти значение. Стоимость - мало места и чуть медленнее пишет. Выгода для большой таблицы огромна: сопоставление 125 855 строк с 41 миллионом позволяет перейти от полного сканирования к поиску. Индексируйте столбцы, к которым вы присоединяетесь, и фильтруйте их. руководство по работе с большими наборами данных охватывает остальную часть работы в этом размере.

И последнее, что стоит знать, прежде чем вы встретитесь с ним. SQL является стандартом, но каждая база данных расширяет его. Функции даты, строковые функции и способы ограничения строк различаются в PostgreSQL, MySQL, SQLite, SQL Server и БигЗапрос. Суть этого руководства везде одинакова. Когда функция не существует, вы обычно говорите на другом диалекте, а не ошибаетесь.

Как это изучить, чтобы это прижилось

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

Во-первых, при извлечении чего-либо из памяти это сохраняется лучше, чем при просмотре. Студенты, которые читали отрывок один раз, а затем проходили тесты на запоминание, неделю спустя вспоминали гораздо больше, чем студенты, которые читали один и тот же отрывок четыре раза, хотя те, кто перечитывал, чувствовали себя более уверенно (Краснее & выбирать карпа, 2006, Психологическая наука, 17(3), 249–255). Применимо здесь: закройте правую колонку листа для поиска ниже и произнесите каждый ответ, прежде чем смотреть. Борьба — это механизм, а не признак того, что вы делаете это плохо.

Второе — это интервал. То же самое общее время исследования, распределенное по дням, а не упакованное в один присест, обеспечивает существенно лучшее запоминание, и эффект сохраняется в сотнях экспериментов (Сепеда, Пашлер, Вул, Викстед & Рорер, 2006, Психологический вестник, 132(3), 354–380). Три двадцатиминутных прохода за три дня превосходят один час сегодня вечером.

В-третьих, почему это руководство постоянно просит вас говорить что-то вслух. Учащиеся, которые объясняют себе проработанный пример по ходу дела, понимают его значительно лучше и лучше переносят его на новые задачи, чем учащиеся, которые читают тот же пример, не объясняя его (Чи, Басок, Льюис, Рейманн & Глейзер, 1989, Когнитивная наука, 13(2), 145–182). SQL — это то место, где это окупается больше всего, потому что ошибка почти никогда не бывает в ключевом слове. Это то, что, по вашему мнению, означает одна строка.

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

Все на одном экране

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

концепцияЧто он делает
GrainЧто означает одна строка. Скажите это как «одна строка на что-то».
Порядок выполненияОТКУДА, ГДЕ, ГРУППИРУЙТЕ, ИМЕЕТ, ВЫБИРАЙТЕ, Упорядочивайте, LIMIT.
Почему WHERE нельзя использовать псевдонимWHERE выполняется перед SELECT, поэтому псевдоним еще не существует.
Почему ORDER BY можетORDER BY выполняется после SELECT.
WHEREФильтрует отдельные строки перед группировкой.
HAVINGФильтрует группы после группировки. Единственный, который видит агрегат.
NULLНеизвестно, не ноль и не пусто. Сравнения с ним не являются ни истинными, ни ложными.
IS NULLЕдинственный правильный тест на пропущенное значение. = NULL никогда не работает.
COALESCEВозвращает первое значение в своем списке, отличное от NULL.
СЧИТАТЬ(*)Подсчитывает строки, включая строки, заполненные NULL.
СЧЕТ(столбец)Подсчитывает строки, в которых этот столбец не равен NULL.
COUNT(DISTINCT столбец)Подсчитывает количество различных значений, игнорируя повторы.
GROUP BYОпределяет, в каких строках вычисляется агрегат.
Правило GROUP BYКаждый выбранный столбец либо группируется, либо агрегируется. Никакого третьего варианта.
INNER JOINСохраняет только совпадающие пары. Несравненные строки исчезают бесшумно.
LEFT JOINСохраняет каждую левую строку, заполняя правую часть NULL там, где ничего не соответствует.
РазветвлениеОдна строка, совпадающая со многими, создает множество строк, повторяющих значения одной стороны.
DISTINCTУдаляет повторяющиеся строки. Прежде чем использовать его, спросите, откуда они взялись.
LIMITВозвращает первые н строк. Самый быстрый способ посмотреть на незнакомую таблицу.
ПсевдонимПсевдоним столбца или таблицы. AS не является обязательным, но более понятным.
CASEЕсли-то. Читается сверху вниз, останавливается на первом совпадении, бесподобный переходит в ELSE.
подзапросЗапрос внутри запроса, в FROM как временная таблица или в WHERE как значение.
КТР (С)Именованный результат определен заранее, поэтому запрос читается в том порядке, в котором он работает.
оконная функцияМатематические вычисления по связанным строкам, которые сохраняют каждую строку. GROUP BY сворачивается, OVER — нет.
PARTITION BYГоворит, какие строки принадлежат одному и тому же окну.
ОТСТАВАНИЕ и ВЕДЕНИЕДостигните предыдущего или следующего ряда. Как строятся изменения от периода к периоду.
первичный ключУникально идентифицирует строку. Никогда не повторяется, никогда NULL.
внешний ключЭтот идентификатор появляется в другой таблице, чтобы указать на него.
индексСтруктура поиска, позволяющая базе данных не считывать каждую строку. Индексируйте то, к чему вы присоединяетесь, и фильтруйте.
Единственная привычка, которую следует сохранить. Прежде чем писать совокупность, произнесите вслух суть того, что вы объединяете. «Одна строка на заказ» или «Одна строка на отзыв». Почти каждое неправильное число в SQL — это правильный расчет, выполненный с той степенью точности, которую вы не планировали, и это одно предложение улавливает его до выполнения запроса. Если не поймает твой, есть общий шлейф диагностики на предмет застревания.

Один искренний вопрос, и мне бы хотелось получить ответы от других людей. Идея, которая заняла у меня больше всего времени, была NULL, потому что я продолжал относиться к этому как к ценности, а не как к отсутствию таковой, и она продолжала почти работать. Какую идею SQL вы дольше всего понимали неправильно и что в итоге исправило это?

Вы можете написать SELECT. Заморозка наступает, когда кто-то говорит: «Присоединяйтесь к ним и скажите мне, почему общие суммы изменились».

SQL для аналитиков состоит из 239 страниц, каждый запрос читается построчно простыми словами, а также практические вопросы, которые печатают ответ и причину, по которой он правильный.

SQL для аналитиков, 19 $ →

Ссылки

Хотите попрактиковаться в этом, а не просто читать?

тот Курс SQL превращает одни и те же концепции в проработанные примеры, обучающие карточки, лабораторию ПРИСОЕДИНЯЙТЕСЬ К Лаборатории, которая запускает реальную базу данных в браузере, и пробный экзамен — в том порядке, в котором они представлены на этой странице. Ничего устанавливать и учетная запись не требуется.

Откройте набор SQL →

Или сразу начните печатать: открыть SQL-практикум, тринадцать запросов, каждый из которых добавляет что-то одно к последнему.