Блог SQL Arena
Туториалы по SQL
Основы: SELECT и фильтрация
4 статьиЧто такое SELECT … FROM в SQL? Выборка из таблицы для начинающих
SELECT — главная команда SQL. С неё начинается любой запрос. Разбираем синтаксис, выбор отдельных колонок, алиасы, вычисляемые поля, частые ошибки и три практических задачи.
Что такое WHERE в SQL? Фильтрация строк для начинающих
WHERE — фильтр строк в SQL. Простыми словами и на пальцах: =, IN, BETWEEN, LIKE, IS NULL и AND/OR. Куча примеров с таблицами «до и после», частые ошибки новичков и мини-практика в конце.
Что такое LIMIT в SQL? Ограничение количества строк для начинающих
LIMIT обрезает результат до N строк. Незаменим для пагинации, топ-N запросов, превью таблиц. Разбираем синтаксис, OFFSET, отличия PostgreSQL и MySQL, частые ошибки и три задачи на тренировку.
Что такое ORDER BY в SQL? Сортировка результата для начинающих
ORDER BY — команда для сортировки результата в SQL. Простыми словами: ASC и DESC, сортировка по нескольким колонкам, NULL-ы в сортировке, комбо с LIMIT для топ-N. Куча примеров и три задачи на потренироваться.
Соединения таблиц (JOIN)
7 статейЧто такое INNER JOIN в SQL? Соединение таблиц для начинающих
INNER JOIN соединяет данные из двух таблиц по общему полю. Самый базовый и самый частый JOIN. Разбираем синтаксис, ON-условие, многотабличные JOIN, частые ошибки и три задачи на тренировку.
Что такое LEFT JOIN в SQL? Разбор для начинающих
LEFT JOIN — соединение таблиц, при котором ВСЕ строки левой таблицы попадают в результат. Если справа пары нет, ставится NULL. Разбираем синтаксис, отличие от INNER JOIN, поиск 'сирот' и три задачи.
Алиасы (AS) в SQL: псевдонимы таблиц и колонок для начинающих
Алиасы — короткие имена для таблиц и колонок в SQL. Делают запросы читаемыми, обязательны при JOIN-ах с одинаковыми колонками. Разбираем синтаксис, обязательные случаи, частые ошибки и три задачи.
FULL OUTER JOIN в SQL: сверка данных и эмуляция в MySQL
Разбираем FULL OUTER JOIN: как получить все строки с обеих сторон, где появляются NULL, зачем он нужен для сверки и как заменить его в MySQL.
CROSS JOIN в SQL: декартово произведение, генерация комбинаций и календарей
Разбираем CROSS JOIN на практике: декартово произведение, генерация всех комбинаций и непрерывных календарей, а также как ловить случайные кросс-джойны.
Self-join в SQL: соединяем таблицу саму с собой
Как с помощью алиасов соединить таблицу саму с собой: иерархии сотрудник→менеджер, сравнение строк внутри таблицы и поиск пар без дублей.
Анти-джойны в SQL: находим строки без совпадений
Три способа найти строки без пары — LEFT JOIN / IS NULL, NOT EXISTS и NOT IN — и почему NOT IN ломается на NULL.
Агрегаты и группировка
25 статейЧто такое COUNT, SUM, AVG, MIN, MAX в SQL? Агрегатные функции для начинающих
Агрегатные функции — это инструмент «посчитать что-то по группе строк». COUNT — сколько строк, SUM — сумма, AVG — среднее, MIN/MAX — минимум и максимум. Простыми словами: разница COUNT(*) и COUNT(column), как NULL влияет на агрегаты, разные сценарии и частые ошибки.
Что такое GROUP BY в SQL? Группировка строк для начинающих
GROUP BY — это команда «схлопни строки в группы и посчитай каждую». Простыми словами: как получить «сколько заказов у каждого клиента» одной строкой кода. Что можно и нельзя писать в SELECT, разница с DISTINCT, GROUP BY по нескольким колонкам и частые ошибки.
Что такое HAVING в SQL? Фильтрация групп для начинающих
HAVING — это фильтр, который работает уже после GROUP BY и применяется к агрегатам. Простыми словами: WHERE отсекает строки на входе, HAVING — группы на выходе. Разберём разницу, типичные кейсы (топ-N, поиск аномалий) и почему WHERE и HAVING путают.
STRING_AGG в SQL: склеиваем строки группы с разделителем и ORDER BY
Как собрать значения из множества строк в одну строку с разделителем и нужным порядком — на PostgreSQL STRING_AGG, MySQL GROUP_CONCAT и ClickHouse arrayStringConcat(groupArray()).
FILTER (WHERE ...) в SQL: как считать условные агрегаты в одном запросе
Как считать несколько сегментированных метрик в одном SELECT через FILTER и не превращать отчёт в набор CASE-выражений.
ARRAY_AGG в PostgreSQL: как собрать строки в массив
Как ARRAY_AGG превращает строки группы в массив, зачем ORDER BY внутри агрегата и какие отличия ждать в MySQL и ClickHouse.
GROUPING SETS в SQL: несколько уровней агрегации одним запросом
Как GROUPING SETS заменяет цепочку UNION ALL, считает разные срезы за один проход и помогает отличать подытоги от настоящих NULL.
ROLLUP в SQL: как добавить подытоги и общий итог в GROUP BY
Как ROLLUP считает детальные строки, промежуточные итоги и общий итог, почему важен порядок столбцов и зачем нужна GROUPING().
PERCENTILE_CONT в PostgreSQL: медиана, p95 и p99 через WITHIN GROUP
Как PERCENTILE_CONT считает непрерывные перцентили через WITHIN GROUP, чем отличается от PERCENTILE_DISC и где применять p50, p95 и p99.
UNNEST в PostgreSQL: как развернуть массив в строки
Как UNNEST превращает массив в строки, зачем WITH ORDINALITY, что происходит с несколькими массивами и чем заменить это в MySQL и ClickHouse.
COUNT(DISTINCT) в SQL: уникальные значения и цена точности
Как работает COUNT(DISTINCT), почему точный подсчёт уникальных значений дорог на больших данных и когда уместны HLL-оценки.
BOOL_AND и BOOL_OR в PostgreSQL: булевы агрегаты по группам
BOOL_AND отвечает «все строки группы истинны», BOOL_OR — «хотя бы одна»; разбираем, как они пропускают NULL, чем полезен EVERY и как повторить это через MIN/MAX в MySQL и ClickHouse.
EVERY в SQL: условие должно выполниться для всей группы
EVERY проверяет, что булево условие истинно для всех не-NULL строк группы; разбираем NULL, BOOL_AND и эмуляцию в MySQL.
STDDEV в SQL: STDDEV_SAMP против STDDEV_POP и поиск выбросов
Чем STDDEV_SAMP отличается от STDDEV_POP, почему голое STDDEV в PostgreSQL означает выборку, как считать mean +/- sd и ловить выбросы по z-score.
VARIANCE в SQL: VAR_SAMP, VAR_POP и связь со STDDEV
Как VAR_SAMP и VAR_POP считают дисперсию в PostgreSQL, почему VARIANCE равна VAR_SAMP и как дисперсия связана со STDDEV.
MODE() WITHIN GROUP: самое частое значение одной строкой
Как достать самое частое значение одним выражением MODE() WITHIN GROUP, по какому правилу разрешаются ничьи и почему это короче и надёжнее связки GROUP BY + COUNT + LIMIT 1.
PERCENTILE_DISC в SQL: дискретные перцентили без интерполяции
PERCENTILE_DISC возвращает настоящее значение из ваших данных без интерполяции: разбираем, чем он отличается от PERCENTILE_CONT и когда брать именно дискретный вариант.
BIT_OR и BIT_AND в PostgreSQL: агрегаты по битовым маскам прав и флагов
BIT_OR собирает все выставленные биты группы, BIT_AND оставляет общие для всех строк, а оператор & читает результат как маску прав и фич-флагов.
JSON_AGG и JSONB_AGG в PostgreSQL: свернуть строки в JSON-массив для ответа API
Сворачиваем строки в JSON-массив через JSON_AGG и JSONB_AGG: упорядочиваем агрегат, собираем вложенный ответ API одним запросом и аккуратно пропускаем NULL.
JSONB_OBJECT_AGG в PostgreSQL: строки ключ-значение сворачиваем в один JSON-объект
Собираем строки настроек в один JSON-объект через JSONB_OBJECT_AGG: как ведёт себя функция при дубликатах ключей и чем она отличается от JSONB_AGG из объектов.
CORR в SQL: корреляция Пирсона одним агрегатом
Один агрегат CORR(y, x) считает корреляцию Пирсона: разбираем знак и силу связи, тихое отбрасывание NULL и связку с REGR_* для линии тренда.
REGR_SLOPE и REGR_INTERCEPT в PostgreSQL: линия тренда и прогноз одним запросом
REGR_SLOPE и REGR_INTERCEPT возвращают наклон и сдвиг линии наименьших квадратов прямо в SQL: коварный порядок аргументов (y, x), контроль выборки через REGR_COUNT и прогноз без выгрузки в Python.
REGR_R2 в SQL: коэффициент детерминации и насколько можно верить тренду
Чем REGR_R2 измеряет качество линейной регрессии в SQL и почему его нельзя читать в отрыве от REGR_SLOPE.
Разворачиваем строки в столбцы: пивот через MAX/SUM FILTER
Как сложить длинную таблицу в широкую кросс-таблицу одним GROUP BY, доверив всю работу агрегатам с оговоркой FILTER.
CUBE в SQL: все срезы группировки за один проход для cross-tab отчётов
Как GROUP BY CUBE одним запросом считает все комбинации столбцов — по каждому измерению и общий итог, как читать NULL-подытоги через GROUPING() и чем CUBE отличается от ROLLUP.
Подзапросы и DISTINCT
4 статьиЧто такое DISTINCT в SQL? Уникальные значения для начинающих
DISTINCT — это «убери дубликаты». Простыми словами: уникальные значения колонки или комбинации колонок, разница с GROUP BY, поведение с NULL и Postgres-фишка DISTINCT ON для «по одной строке на группу». С таблицами before/after и частыми ошибками.
Что такое IN с подзапросом в SQL? Проверка членства для начинающих
IN с подзапросом — это «выбери строки, где значение колонки есть в результате другого запроса». Простыми словами: фильтрация по динамическому списку, разница со списком литералов, главная ловушка NOT IN с NULL и сравнение с EXISTS. С таблицами и частыми ошибками.
Что такое EXISTS в SQL? Проверка наличия для начинающих
EXISTS — это «есть ли хотя бы одна строка, удовлетворяющая условию». Простыми словами: фильтр на наличие связанной записи (например «клиенты, у которых есть хотя бы один заказ»), отличие от IN с подзапросом, NOT EXISTS и поведение с NULL.
Что такое скалярный подзапрос в SQL? Одно значение в SELECT для начинающих
Скалярный подзапрос — это SELECT, который возвращает ровно одно значение и встаёт прямо на место колонки или в WHERE. Простыми словами: вытянуть одно поле из связанной таблицы, добавить итоговую цифру к каждой строке отчёта, использовать как «константу» в условии. С таблицами и частыми ошибками.
Оконные функции
10 статейЧто такое ROW_NUMBER в SQL? Нумерация строк для начинающих
ROW_NUMBER — это «дай каждой строке свой номер по порядку». Простыми словами: первая оконная функция, которую стоит изучить. Нумерация по убыванию, нумерация внутри групп через PARTITION BY, классические задачи top-N в каждой группе и удаление дубликатов. С таблицами и частыми ошибками.
Что такое RANK и DENSE_RANK в SQL? Ранжирование с ничьими для начинающих
RANK и DENSE_RANK — это ранжирование, где одинаковые значения получают одинаковый ранг. Простыми словами: разница между ROW_NUMBER (всегда уникально), RANK (одинаковые значения → одинаковый ранг с пропусками после) и DENSE_RANK (одинаковый ранг без пропусков). С таблицами, олимпийским сравнением и частыми ошибками.
Что такое PARTITION BY в SQL? Группы внутри окна для начинающих
PARTITION BY — это часть OVER, которая делит строки на группы для оконных функций. Простыми словами: то же что GROUP BY, но строки не схлопываются — каждая остаётся, и к ней дописывается агрегат по её группе. Разница с GROUP BY, типичные применения и поведение агрегатов в окне.
Что такое LAG и LEAD в SQL? Соседние строки в окне для начинающих
LAG и LEAD — это «возьми значение из предыдущей или следующей строки окна». Простыми словами: разница между соседними событиями (день-к-дню), время до следующего действия, изменение цены — задачи, которые без оконных функций требовали бы джойна таблицы саму к себе. С таблицами и частыми ошибками.
Оконные рамки в SQL: ROWS/RANGE, нарастающие итоги и ловушка LAST_VALUE
Разбираемся, как устроены оконные рамки ROWS и RANGE BETWEEN, считаем нарастающие итоги и скользящие средние и обходим классическую ловушку с LAST_VALUE.
Оконные функции в SQL: ROW_NUMBER, RANK, LAG/LEAD на практике
Оконные функции — главный инструмент SQL-аналитика. Разберём ROW_NUMBER, RANK, LAG/LEAD и PARTITION BY на реальных задачах: топ-N в категории, day-over-day метрики, кумулятивные суммы.
NTILE в SQL: как делить строки на квартили, децили и равные когорты
Как NTILE(n) делит упорядоченные строки на почти равные корзины, куда попадает остаток и почему это не то же самое, что WIDTH_BUCKET.
FIRST_VALUE и LAST_VALUE в SQL: первое, последнее и ловушка оконного фрейма
Как FIRST_VALUE и LAST_VALUE берут крайние значения окна, почему LAST_VALUE часто возвращает текущую строку и какой фрейм писать явно.
PERCENT_RANK и CUME_DIST в SQL: как понять позицию строки в диапазоне от 0 до 1
PERCENT_RANK и CUME_DIST дают относительный ранг строки в шкале 0..1: формула (rank-1)/(rows-1), разница функций, ничьи и детерминизм.
NTH_VALUE в SQL: как взять n-е значение окна и не попасться на ловушку фрейма
Как NTH_VALUE берёт n-ю строку оконной рамки, почему без явного ROWS-фрейма появляются NULL и чем заменить второй уникальный максимум.
CTE (WITH)
5 статейЧто такое WITH … AS (CTE) в SQL? Common Table Expressions для начинающих
WITH … AS — это «именованный временный результат», он же CTE (Common Table Expression). Простыми словами: способ разбить сложный запрос на читаемые шаги, переиспользовать промежуточные расчёты и вообще писать SQL, который потом не противно перечитывать. С таблицами и частыми ошибками.
Несколько CTE в одном запросе: цепочки WITH для начинающих
Несколько CTE через запятую — это способ выстроить запрос «по шагам»: сначала посчитали одно, потом на основе этого второе, потом сложили в финальный результат. Простыми словами: цепочки CTE, переиспользование промежуточных результатов и рекурсивные CTE для работы с иерархиями.
Рекурсивные CTE в SQL: WITH RECURSIVE для деревьев, графов и числовых рядов
Как устроен WITH RECURSIVE: якорь плюс рекурсивный шаг через UNION ALL, обход оргструктуры и графов, генерация числовых рядов и защита от бесконечных циклов.
LATERAL JOIN в PostgreSQL: top-N на группу и подзапросы со ссылкой на соседние таблицы
Как LATERAL даёт подзапросу ссылаться на колонки предыдущих таблиц во FROM, решает задачу top-N на группу и почему LEFT JOIN LATERAL ... ON true сохраняет внешние строки.
generate_series в PostgreSQL: календарная ось, числовые ряды и заполнение пропусков нулями
Табличная функция generate_series строит непрерывный ряд чисел, дат и таймстампов — лучший способ получить календарную ось без дыр и показать пустые периоды.
Изменение данных (DML)
10 статейЧто такое INSERT в SQL? Добавление строк для начинающих
INSERT — это команда «добавить новую строку в таблицу». Простыми словами: базовый синтаксис, batch-вставка нескольких строк за раз, INSERT FROM SELECT, RETURNING для возврата id, и UPSERT через ON CONFLICT для идемпотентных вставок. С таблицами before/after и частыми ошибками.
Что такое UPDATE в SQL? Изменение строк для начинающих
UPDATE — это команда «поменять данные в существующих строках». Простыми словами: что меняем, как обязательно сужать WHERE, как поменять сразу несколько колонок. Таблицы before/after, типичные ловушки новичков, мини-резюме и три задачки на закрепление.
Что такое DELETE в SQL? Удаление строк для начинающих
DELETE — это команда «убрать строки из таблицы». Простыми словами: что удаляем, почему WHERE обязателен, soft-delete vs hard-delete, разница с TRUNCATE и каскадное удаление через FK. Таблицы before/after, частые ошибки новичков, мини-резюме и три задачки.
UPSERT в PostgreSQL: INSERT ... ON CONFLICT на практике
Как одним запросом вставлять или обновлять строки через INSERT ... ON CONFLICT, использовать EXCLUDED, делать идемпотентные вставки и атомарные счётчики.
MERGE в PostgreSQL 15+: MATCHED / NOT MATCHED, upsert и синхронизация таблиц
Разбираем оператор MERGE в PostgreSQL 15+: ветки MATCHED и NOT MATCHED, паттерны upsert и синхронизации, и когда он лучше старого доброго ON CONFLICT.
INSERT ... ON CONFLICT DO NOTHING в PostgreSQL: идемпотентные вставки без ошибок
Как ON CONFLICT DO NOTHING превращает INSERT в идемпотентную операцию, чем conflict target отличается от имени ограничения, почему RETURNING молчит про пропущенные строки и как сеять данные пачками.
RETURNING в PostgreSQL: как получить id и новые значения строк без второго запроса
Как клауза RETURNING на INSERT/UPDATE/DELETE возвращает сгенерированные id и новые значения столбцов за один проход, без повторного SELECT.
DELETE ... USING в PostgreSQL: как удалять строки по другой таблице без подзапросов
Как DELETE ... USING фильтрует строки по другой таблице через JOIN, чем он лучше WHERE IN с подзапросом и как выглядит многотабличный DELETE в MySQL.
UPDATE ... FROM в PostgreSQL: как обновлять таблицу по JOIN и подзапросу
UPDATE ... FROM подставляет в строки значения из другой таблицы или агрегата; разбираем синтаксис и ловушку пропущенного WHERE.
CTE + DELETE ... RETURNING в PostgreSQL: как перенести строки в архив одним оператором
DELETE ... RETURNING внутри WITH переносит строки в архив одним атомарным оператором, без гонки между DELETE и INSERT.
Структура (DDL)
10 статейЧто такое CREATE TABLE в SQL? Создание таблицы для начинающих
CREATE TABLE — это команда «создать новую таблицу». Простыми словами: какие колонки и какого типа, что такое NOT NULL, DEFAULT, PRIMARY KEY и FOREIGN KEY, и почему важно подумать о схеме сразу. С таблицами before/after, частыми ошибками новичков и тремя задачками.
Что такое ALTER TABLE в SQL? Изменение структуры таблицы для начинающих
ALTER TABLE — это команда «поменять структуру существующей таблицы». Простыми словами: добавить колонку, удалить, переименовать, сменить тип, добавить и снять constraint. Плюс главная боль ALTER на проде — длинные блокировки таблицы и паттерн «add → backfill → drop» для безопасных миграций.
CHECK-ограничения в SQL: как закреплять бизнес-правила на уровне базы данных
Как с помощью CHECK закреплять бизнес-правила в схеме: положительные суммы, допустимые статусы, диапазоны дат и многоколоночные проверки.
FOREIGN KEY ON DELETE: CASCADE, SET NULL и RESTRICT на практике
Что происходит с дочерними строками при удалении родителя и как выбрать между CASCADE, SET NULL, RESTRICT и NO ACTION без потери данных.
NOT VALID + VALIDATE: как добавить FK и CHECK без долгих блокировок
NOT VALID добавляет FK или CHECK мгновенно, а VALIDATE CONSTRAINT досканирует старые строки без остановки записи.
Генерируемые столбцы в PostgreSQL: GENERATED ALWAYS AS STORED
Как хранить производную величину в одном месте через GENERATED ALWAYS AS (...) STORED, индексировать её и не путать с триггерами и представлениями.
Частичный UNIQUE-индекс: уникальность не для всей таблицы, а только для нужных строк
Как навязать уникальность только части строк: одна активная запись на ключ, повторная регистрация после soft-delete и единственный default в группе.
Секционирование по диапазону в PostgreSQL: партиции по времени
Как разбить большую таблицу по диапазону дат, мгновенно удалять старые данные и заставить планировщик читать только нужные секции.
Триггеры в SQL: BEFORE/AFTER, NEW/OLD и паттерн updated_at
Как работают триггеры BEFORE/AFTER и ROW/STATEMENT, что возвращать из функции, паттерн auto-updated_at, аудит изменений и когда триггеры вредят.
Материализованные представления в SQL: кэш для дорогих запросов
Как материализованное представление кэширует результат тяжёлого запроса, чем REFRESH отличается от обычной вьюхи и когда лучше взять сводную таблицу.
Строки и даты
41 статьяЧто такое LOWER, UPPER, LENGTH в SQL? Строковые функции для начинающих
Строковые функции — повседневный инструмент SQL: нормализация регистра (LOWER, UPPER), длина строки (LENGTH), обрезка пробелов (TRIM), подстрока (SUBSTRING), замена (REPLACE). Простыми словами: case-insensitive поиск, очистка данных от пробелов и Unicode-нюансы.
Что такое CONCAT в SQL? Склейка строк для начинающих
CONCAT — это «склей строки в одну». Простыми словами: три формы (||, CONCAT, CONCAT_WS), как они по-разному обращаются с NULL и почему CONCAT_WS — лучший выбор для адресов и имён. С таблицами и частыми ошибками.
Что такое EXTRACT в SQL? Год, месяц, день из даты для начинающих
EXTRACT — это «достань кусок из даты»: год, месяц, день, час, день недели. Простыми словами: как сгруппировать данные по году/месяцу, отфильтровать по дню недели, посчитать секунды через EPOCH. Сравнение с DATE_TRUNC и отличия PostgreSQL и MySQL.
DATE_TRUNC в SQL: как группировать даты по часу, дню, неделе и месяцу
DATE_TRUNC приводит метки времени к началу периода, чтобы корректно группировать события по часам, дням, неделям и месяцам.
NOW(), CURRENT_DATE и INTERVAL в SQL: как правильно фильтровать данные по датам
NOW(), CURRENT_DATE и INTERVAL помогают строить быстрые фильтры за последние дни, текущий месяц и другие временные окна.
CAST и :: в SQL: как явно приводить типы в PostgreSQL
CAST(x AS type) и оператор :: явно приводят значение к другому типу; разбираем округление numeric, ошибки на грязных строках и отличия MySQL и ClickHouse.
TRIM, SUBSTRING и REPLACE в SQL: как очищать и приводить строки в порядок
TRIM, SUBSTRING и REPLACE помогают убирать лишние символы, вырезать фрагменты строк и собирать стабильные ключи для джойнов.
SPLIT_PART в PostgreSQL: как взять часть строки по разделителю
SPLIT_PART разбивает строку по фиксированному разделителю и быстро достает нужное поле, например домен, сегмент пути или код.
ILIKE в PostgreSQL: поиск без учёта регистра
ILIKE выполняет поиск по шаблону без учета регистра, а pg_trgm помогает ускорить такие запросы на больших таблицах.
LEFT и RIGHT в SQL: как взять начало или конец строки
Разбираем LEFT и RIGHT в PostgreSQL: как брать крайние символы, маскировать карты, использовать отрицательную длину и не ошибиться при переносе в MySQL.
POSITION и STRPOS в SQL: как найти подстроку внутри строки
Показываем, чем отличаются POSITION и STRPOS, почему индексация начинается с единицы, как трактовать ноль и когда переходить к SUBSTRING или регуляркам.
LPAD и RPAD в SQL: как дополнить строку слева или справа
Практический разбор LPAD и RPAD: дополнение нулями, фиксированная ширина, обрезка длинных строк и различия PostgreSQL, MySQL и ClickHouse.
INITCAP в SQL: как привести имена и названия к красивому регистру
INITCAP в PostgreSQL делает первую букву каждого слова заглавной, а остальные строчными; разбираем приведение имен и городов и поломки на апострофах, дефисах и локалях.
REPEAT в SQL: как повторять строку для разделителей, плейсхолдеров и текстовых диаграмм
REPEAT(str, n) повторяет строку n раз и собирает разделители отчетов, плейсхолдеры для IN-списков и текстовые бар-чарты прямо в выдаче SQL.
REVERSE в SQL: как развернуть строку и зачем это бывает нужно
Разбираем REVERSE как инструмент для работы с суффиксами, палиндромами и сегментами строк, включая Unicode и отличия PostgreSQL, MySQL и ClickHouse.
CHAR_LENGTH в SQL: как считать символы, а не байты
CHAR_LENGTH возвращает число символов строки, OCTET_LENGTH — её размер в байтах, а LENGTH считает то символы, то байты в зависимости от PostgreSQL, MySQL или ClickHouse.
REGEXP_REPLACE в SQL: как заменять текст по шаблону
REGEXP_REPLACE заменяет в строке все совпадения по регулярному выражению: разбираем сигнатуру в PostgreSQL, флаги g и i, обратные ссылки на группы, расхождения POSIX и PCRE, аналоги в MySQL и ClickHouse.
REGEXP_MATCHES в PostgreSQL: как доставать группы из строки
Как REGEXP_MATCHES возвращает группы захвата массивом text[], что делает флаг g и почему при отсутствии совпадения строка выпадает из результата.
REGEXP_SPLIT_TO_ARRAY в SQL: разбор строк по сложному разделителю
REGEXP_SPLIT_TO_ARRAY разбивает строку по regex-разделителю в массив text[]: переменные пробелы, смесь запятой и точки с запятой, пустые элементы по краям и разворот через UNNEST.
TRANSLATE в SQL: посимвольная замена, удаление и транслитерация
TRANSLATE заменяет символы первого набора на символы того же номера во втором, удаляет символы без пары и помогает строить slug, но это не REPLACE.
BTRIM, LTRIM и RTRIM в SQL: точная очистка краев строки
Разбираем BTRIM, LTRIM и RTRIM: как убирать пробелы, нули, слеши и другие символы с краев строки без повреждения середины значения.
FORMAT в PostgreSQL: шаблоны строк с %s, %I и %L и безопасный динамический SQL
format() в PostgreSQL собирает строку по шаблону через %s, а %I и %L безопасно подставляют идентификаторы и литералы в динамический SQL вместо хрупкой конкатенации.
STARTS_WITH в PostgreSQL: буквальная проверка префикса вместо LIKE
STARTS_WITH(str, prefix) в PostgreSQL 11+ проверяет начало строки буквально, без экранирования %. Разбираем регистр, индексы text_pattern_ops, NULL и эквиваленты в MySQL и ClickHouse.
ASCII и CHR в SQL: код символа Unicode и обратно
ascii() возвращает кодовую точку первого символа, chr() собирает символ по коду; в PostgreSQL оба работают с полным Unicode, а в MySQL и ClickHouse поведение иное.
to_hex в PostgreSQL: перевод целого числа в шестнадцатеричную строку
Функция to_hex(int) превращает число в hex-строку для цветов, битовых масок и отладки флагов; как сделать обратное преобразование и чем отличаются MySQL и ClickHouse.
AGE в PostgreSQL: календарный интервал между датами
AGE возвращает разницу как годы, месяцы и дни, поэтому подходит для возраста и стажа, но не заменяет подсчет точных суток.
DATE_PART в SQL: извлечение частей даты и времени
DATE_PART достает год, месяц, день недели, epoch и другие поля из timestamp или interval, но требует внимания к типам и нумерации.
EXTRACT(EPOCH FROM ...) в SQL: интервал в секунды и метка времени в Unix-время
EXTRACT(EPOCH FROM ...) возвращает длительность интервала в секундах, а от метки времени — Unix-время; разбираем оба режима, деление на 60 и 3600 и обратный to_timestamp.
TO_CHAR в PostgreSQL: форматирование дат, времени и чисел по шаблону
TO_CHAR превращает даты, timestamp и числа в строки по текстовому шаблону: YYYY-MM-DD, HH24:MI, названия месяцев, разделители разрядов и отличия от MySQL.
TO_DATE в PostgreSQL: парсинг строки в дату по шаблону формата
TO_DATE парсит строку в date по шаблону формата: разбираем синтаксис, чем он лучше ::date, ловушку нестрогого разбора и двузначный год.
TO_TIMESTAMP в PostgreSQL: парсинг строк и сборка времени из Unix-эпохи
Два режима TO_TIMESTAMP в PostgreSQL: разбор строки по шаблону формата в timestamptz и сборка момента из секунд Unix-эпохи, со всеми нюансами часовых поясов.
CURRENT_TIMESTAMP в SQL: время транзакции против реального сейчас
CURRENT_TIMESTAMP возвращает timestamptz и фиксируется на старте транзакции; разбираем отличие от LOCALTIMESTAMP и clock_timestamp для аудита и DEFAULT.
CURRENT_DATE, CURRENT_TIME и CURRENT_TIMESTAMP в SQL
CURRENT_DATE, CURRENT_TIME и CURRENT_TIMESTAMP — значения SQL без скобок: дата, время суток с поясом и полный момент. Разбираем типы, фильтры WHERE и DEFAULT.
Арифметика дат в SQL: прибавление дней, интервалы и разница timestamp
Как прибавлять дни к date, вычитать даты в число суток и прибавлять interval к timestamp в PostgreSQL, MySQL и ClickHouse.
MAKE_DATE и MAKE_TIME в PostgreSQL: сборка даты и времени из частей
MAKE_DATE и MAKE_TIME безопасно собирают значения из числовых колонок и сразу показывают ошибки диапазона вместо тихой нормализации.
make_timestamp и make_interval в PostgreSQL: сборка timestamp и interval из чисел
make_timestamp собирает timestamp из чисел года, месяца, дня и времени, а make_interval строит interval из именованных аргументов — без хрупких форматных строк.
AT TIME ZONE в PostgreSQL: перевод времени между зонами
AT TIME ZONE либо назначает часовой пояс наивному timestamp, либо показывает момент времени в локальной зоне пользователя.
JUSTIFY_INTERVAL в PostgreSQL: нормализация интервалов без самообмана
JUSTIFY_INTERVAL переносит часы в дни и дни в месяцы, но его 30-дневный месяц не равен календарной логике бизнеса.
DATE_BIN в PostgreSQL: произвольные временные корзины для метрик
DATE_BIN группирует события в интервалы любой ширины от выбранной точки отсчета, когда DATE_TRUNC слишком груб для аналитики.
Оператор OVERLAPS в SQL: поиск пересечений периодов и конфликтов
Как через OVERLAPS проверить, пересекаются ли два периода, и находить накладки в бронированиях и сменах в PostgreSQL.
TIMESTAMPTZ в PostgreSQL: момент времени, UTC и локальный вывод
TIMESTAMPTZ хранит момент времени как UTC и применяет зону сессии при выводе, поэтому его берут для событий, аудита и расписаний с учетом клиента.
CASE и NULL
4 статьиЧто такое CASE WHEN в SQL? Условная логика для начинающих
CASE WHEN — это «if/else внутри SQL». Простыми словами: как поставить условие прямо в SELECT, разница между searched CASE и simple CASE, бакетирование чисел в категории, pivot одной формулой и условные агрегаты. С таблицами и частыми ошибками.
Что такое COALESCE в SQL? Замена NULL для начинающих
COALESCE — это «верни первое не-NULL значение из списка». Простыми словами: дефолты для отсутствующих данных, fallback-цепочки (никнейм → имя → 'Гость'), безопасные арифметические операции и NULLIF в паре. С таблицами и частыми ошибками.
Что такое NULLIF в SQL? Безопасное деление и очистка для начинающих
NULLIF — это «верни NULL, если два значения равны». Простыми словами: безопасное деление через NULLIF(x, 0), очистка плейсхолдеров типа '' или 'unknown', связка с COALESCE для аккуратной обработки данных. С таблицами и частыми ошибками.
NULL и IS DISTINCT FROM в SQL: как правильно сравнивать значения с NULL
Почему = NULL никогда не истинно и как IS DISTINCT FROM решает проблему сравнения столбцов с NULL.
Прочее
53 статьиЦелочисленное деление в SQL: оператор /, div, DIV и остаток MOD
Когда оператор / в PostgreSQL отсекает дробь, почему лишний cast превращает 7/2 в 3.5, чем выручает функция div(a, b), как с тем же справляются DIV в MySQL и intDiv в ClickHouse и почему рядом почти всегда стоит MOD.
WIDTH_BUCKET в SQL: равные интервалы гистограммы прямо в запросе
WIDTH_BUCKET раскладывает число по равным по ширине корзинам, ловит выход за границы в корзины 0 и n+1 и строит распределения через GROUP BY.
Операторы JSONB -> и ->>: чтение полей и текста
Как операторы -> и ->> читают поля JSONB, достают элементы массивов, строят цепочки и требуют явного приведения типов.
Операторы JSONB #> и #>>: вложенные пути без лесенки
Как #> и #>> читают вложенные значения по text[]-пути, смешивают ключи с индексами и когда вместо них нужен jsonb_path_query.
jsonb_build_object в PostgreSQL: JSON-объект из колонок
Как jsonb_build_object собирает объект из пар ключ-значение, сохраняет типы, строит вложенные ответы и отличается от to_jsonb.
jsonb_build_array в PostgreSQL: JSON-массив из разных типов
Как jsonb_build_array собирает позиционный JSON-массив, сохраняет порядок и типы и чем отличается от to_jsonb SQL-массива.
Составной индекс в SQL: левый префикс, сортировка и INCLUDE
Правильный порядок колонок в составном индексе закрывает фильтр, ORDER BY и index-only scan, а неправильный оставляет плану лишнюю работу.
jsonb_array_elements: разворот JSONB-массива в строки
jsonb_array_elements раскладывает JSONB-массив на строки, по строке на элемент: фильтрация и джойн по элементам, индекс через WITH ORDINALITY, вариант _text.
jsonb_array_length: безопасная длина JSON-массива
Как jsonb_array_length считает элементы массива, почему падает на non-array и как jsonb_typeof защищает фильтры и агрегаты.
jsonb_set в PostgreSQL: точечное обновление JSONB
Как jsonb_set заменяет значение по пути, работает с create_missing, обновляет вложенные поля в UPDATE и чем удаление отличается от правки.
jsonb_each в PostgreSQL: разворот JSON-объекта в строки key/value
jsonb_each разворачивает JSONB-объект в строки key/value: перебор динамических ключей, фильтрация, агрегация и когда брать jsonb_each_text.
jsonb_object_keys: ключи JSONB-объекта строками
jsonb_object_keys разворачивает ключи верхнего уровня JSONB в строки: разведать схему колонки, проверить наличие поля и собрать ключи через array_agg.
JSONB-операторы проверки ключей в PostgreSQL: ?, ?| и ?&
Операторы ?, ?| и ?& в jsonb проверяют наличие ключей верхнего уровня, ускоряются GIN-индексом и конфликтуют с плейсхолдерами драйверов.
to_jsonb в PostgreSQL: вся строка одним JSON-объектом
Как to_jsonb превращает любое значение, строку или массив в jsonb, сохраняя типы, и чем он умнее json_build_object и старого row_to_json.
Удаление из JSONB: операторы - и #- в PostgreSQL
Как операторы - и #- удаляют ключи, индексы массивов и вложенные значения из JSONB без пересборки документа в приложении.
JSONB || в PostgreSQL: поверхностное слияние и патчи
Как оператор || сливает JSONB-объекты, почему правый ключ побеждает, что происходит с массивами и где нужен jsonb_set.
Read-only роль в PostgreSQL: доступ к данным без права что-то сломать
Соберите роль для BI правильно: USAGE на схему, SELECT на текущие таблицы и default privileges, чтобы будущие таблицы не выпали.
CREATE ROLE в PostgreSQL: пользователи, группы и наследование прав
В PostgreSQL роль может быть пользователем или группой; разберём LOGIN/NOLOGIN, INHERIT, SET ROLE и атрибуты уровня кластера.
REVOKE в SQL: как отзывать права без сюрпризов от PUBLIC и ролей
Отозвать доступ сложнее, чем выдать: проверьте прямые гранты, PUBLIC, членство в ролях и цепочки WITH GRANT OPTION.
GRANT в SQL: привилегии, роли и минимально достаточный доступ
GRANT задаёт реальную границу доступа: права на схемы, таблицы и колонки, членство в ролях и осторожное делегирование через grant option.
Атомарный счётчик в SQL: почему n = n + 1 безопаснее, чем считать в приложении
Счётчик нельзя увеличивать через read-modify-write; один UPDATE с n = n + 1 сериализует инкременты и сохраняет точность.
Условный UPDATE: как атомарно проверить условие и изменить данные
Перенесите предусловие внутрь UPDATE, чтобы списания, смены статуса и compare-and-swap не проигрывали гонку между SELECT и записью.
SELECT FOR UPDATE: построчные блокировки, очереди и дедлоки в PostgreSQL
SELECT FOR UPDATE защищает чтение-потом-запись от гонок; разберём режимы блокировок, NOWAIT, SKIP LOCKED и порядок захвата строк.
EXPLAIN ANALYZE BUFFERS: как читать реальный план PostgreSQL
План с ANALYZE показывает фактические строки, loops и буферы; по ним видно, где планировщик ошибся и почему запрос читает лишнее.
CREATE INDEX CONCURRENTLY: как создать индекс в PostgreSQL без остановки записей
Как построить и удалить индекс на горячей таблице без простоя, почему команда не живёт в транзакции и чем опасен INVALID-индекс.
NOT EXISTS против NOT IN: как безопасно искать строки, которых нет в другой таблице
Один NULL в подзапросе способен сломать NOT IN; разберём, почему NOT EXISTS обычно безопаснее и когда уместен LEFT JOIN IS NULL.
jsonb_pretty в PostgreSQL: читаемый вывод JSONB с отступами
jsonb_pretty форматирует JSONB с отступами и переносами строк для отладки в psql; разбираем порядок ключей и когда формат включать не стоит.
jsonb_typeof в PostgreSQL: проверяем тип JSON до того, как запрос упадёт
jsonb_typeof отдаёт тип JSON-значения текстом и страхует jsonb_array_length, арифметику и валидацию полуструктурированных данных от падения.
jsonb_agg в PostgreSQL: строки группы в JSON-массив
Как jsonb_agg сворачивает строки в массив JSONB, управляет порядком, фильтрует элементы и требует COALESCE для пустых групп.
Sargable WHERE: как писать условия, которые используют индекс
Функция вокруг столбца превращает индекс в декорацию; покажем, как заменить EXTRACT, date(), lower() и LIKE на индексные условия.
ROUND в SQL: округление до целого, numeric vs double, деньги
ROUND округляет до ближайшего целого, но половинки и тип double меняют результат; разберём стратегии округления и расчёт денег на numeric.
ROUND(x, n) в SQL: знаки после запятой, отрицательное n и numeric для денег
ROUND(x, n) округляет до n знаков после запятой; в PostgreSQL двухаргументная форма требует numeric. Разбираем отрицательное n, валютный вывод и поведение ClickHouse.
CEIL и CEILING в SQL: округление вверх, страницы и бакеты
CEIL отвечает на вопрос «сколько целых единиц нужно»; используйте его для пагинации, упаковки и верхних границ диапазонов.
FLOOR в SQL: округление вниз, бакеты и отрицательные числа
FLOOR всегда идёт к меньшему целому, поэтому на отрицательных значениях отличается от TRUNC и влияет на корзины и диапазоны.
TRUNC в SQL: усечение числа к нулю без округления
TRUNC срезает дробную часть, не глядя на следующие цифры; разберём второй аргумент, деньги и отличие от FLOOR на возвратах.
ABS в SQL: модуль, отклонение и сравнение с допуском
ABS превращает разницу в расстояние: удобно для сверок, поиска отклонений и сравнений с epsilon, но в WHERE есть индексная ловушка.
MOD и % в SQL: остаток от деления, шардирование и знак
Остаток от деления делит строки на чётные, когорты и шарды, но отрицательные значения и нулевой делитель требуют внимания.
POWER в SQL: степени, корни и сложный процент
POWER(base, exponent) возводит число в степень: степени, корни через дробный показатель 1.0/n, сложный процент и проверка на переполнение.
SQRT в SQL: квадратный корень без сюрпризов
SQRT возвращает квадратный корень: как он ведёт себя в PostgreSQL, почему падает на отрицательном входе и как им считать расстояния и стандартное отклонение.
EXP и LN в SQL: экспонента, логарифмы и рост
Как EXP и LN считают натуральные логарифмы, средние геометрические, темпы роста и требуют строго положительного входа.
LOG в SQL: десятичный логарифм, произвольное основание и ловушка MySQL
В PostgreSQL LOG(x) — десятичный логарифм, а LOG(b, x) — по любому основанию; разбираем отличие от MySQL и применение логарифмов для шкал и порядков величины.
SIGN в SQL: знак числа для трендов и отклонений
Как SIGN возвращает -1, 0 или 1, отделяет направление от величины и помогает классифицировать рост, падение и нулевое изменение.
GREATEST и LEAST в SQL: построчный максимум и минимум по столбцам
GREATEST и LEAST возвращают максимум и минимум столбцов внутри одной строки, зажимают число в диапазон через вложенный вызов и по-разному обрабатывают NULL в PostgreSQL, MySQL и ClickHouse.
RANDOM() в SQL: случайные строки, сэмплинг и сиды
RANDOM() возвращает дробь из [0, 1): как тянуть случайные строки, почему ORDER BY RANDOM() тормозит на масштабе и когда брать TABLESAMPLE, floor и setseed.
UNION и UNION ALL в SQL: как объединять результаты SELECT-запросов
Выберите правильный оператор для склейки выборок: где нужен быстрый UNION ALL, когда оправдан UNION и почему порядок столбцов важнее имён.
INTERSECT в SQL: как найти строки, которые есть в обеих выборках
INTERSECT возвращает строки, присутствующие в результатах обоих SELECT; разберём INTERSECT ALL, кратность, NULL, приоритет операторов и замену через EXISTS/JOIN.
EXCEPT в SQL: как найти строки, которые есть в одной выборке, но отсутствуют в другой
EXCEPT вычитает второй набор из первого, помогает искать расхождения и отличается от NOT EXISTS обработкой дублей и NULL.
JSONB ->> в PostgreSQL: как извлечь поле из JSON как текст
Оператор ->> достаёт скаляр из JSONB как text; покажем разницу с ->, приведение типов, NULL для отсутствующих ключей и индексы.
JSONB @> в PostgreSQL: containment-поиск, вложенные фрагменты и GIN-индексы
Оператор @> проверяет, содержит ли JSONB нужный фрагмент; разберём вложенные объекты, массивы, типы и выбор между GIN и ->>.
GIN-индексы для JSONB в PostgreSQL: jsonb_ops, jsonb_path_ops и индексы по выражениям
Разбираем, когда JSONB-фильтрам нужен GIN, чем jsonb_ops отличается от jsonb_path_ops и когда дешевле индекс по выражению.
Как читать план запроса: EXPLAIN и EXPLAIN (ANALYZE, BUFFERS)
Практический разбор плана запроса в PostgreSQL: Seq Scan против Index Scan, оценки против реальности и как поймать недостающий индекс.
Частичные индексы в PostgreSQL: индексируем только горячие строки
Как с помощью CREATE INDEX ... WHERE покрыть только активные строки, получить меньший и более быстрый индекс и сделать UNIQUE-ограничение, дружащее с soft-delete.
Очереди задач в SQL: SELECT ... FOR UPDATE SKIP LOCKED
Как заставить десяток воркеров безопасно разбирать задачи из таблицы-очереди, не блокируя друг друга — с помощью FOR UPDATE SKIP LOCKED в PostgreSQL.