Блог 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: как найти совпадения и расхождения между таблицами
Разбираем 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: как собрать несколько строк в одну
Как собрать значения из множества строк в одну строку с разделителем и нужным порядком — на 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 в SQL: как проверить «все» и «хотя бы один»
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 в PostgreSQL означает выборку, как считать mean +/- sd и ловить выбросы по z-score.
VARIANCE в SQL: как посчитать разброс данных
Как VAR_SAMP и VAR_POP считают дисперсию в PostgreSQL, почему VARIANCE равна VAR_SAMP и как дисперсия связана со STDDEV.
MODE в SQL: как найти самое частое значение в столбце
Как достать самое частое значение одним выражением MODE() WITHIN GROUP, по какому правилу разрешаются ничьи и почему это короче и надёжнее связки GROUP BY + COUNT + LIMIT 1.
PERCENTILE_DISC в SQL: перцентиль, который возвращает реальное значение из таблицы
PERCENTILE_DISC возвращает настоящее значение из ваших данных без интерполяции: разбираем, чем он отличается от PERCENTILE_CONT и когда брать именно дискретный вариант.
BIT_OR, BIT_AND и BIT_XOR в SQL: как агрегировать битовые флаги
BIT_OR собирает все выставленные биты группы, BIT_AND оставляет общие для всех строк, а оператор & читает результат как маску прав и фич-флагов.
JSON_AGG и JSONB_AGG в PostgreSQL: как собрать строки в JSON-массив
Сворачиваем строки в JSON-массив через JSON_AGG и JSONB_AGG: упорядочиваем агрегат, собираем вложенный ответ API одним запросом и аккуратно пропускаем NULL.
JSONB_OBJECT_AGG в PostgreSQL: как собрать JSONB-объект из строк
Собираем строки настроек в один JSON-объект через JSONB_OBJECT_AGG: как ведёт себя функция при дубликатах ключей и чем она отличается от JSONB_AGG из объектов.
CORR в SQL: как измерить связь между двумя колонками прямо в базе
Один агрегат CORR(y, x) считает корреляцию Пирсона: разбираем знак и силу связи, тихое отбрасывание NULL и связку с REGR_* для линии тренда.
REGR_SLOPE и REGR_INTERCEPT в PostgreSQL: линия тренда прямо в SQL
REGR_SLOPE и REGR_INTERCEPT возвращают наклон и сдвиг линии наименьших квадратов прямо в SQL: коварный порядок аргументов (y, x), контроль выборки через REGR_COUNT и прогноз без выгрузки в Python.
REGR_R2 в PostgreSQL: как понять, можно ли доверять тренду
Чем REGR_R2 измеряет качество линейной регрессии в SQL и почему его нельзя читать в отрыве от REGR_SLOPE.
Пивот в PostgreSQL через FILTER: как развернуть строки в столбцы
Как сложить длинную таблицу в широкую кросс-таблицу одним GROUP BY, доверив всю работу агрегатам с оговоркой FILTER.
CUBE в PostgreSQL: как считать итоги по всем комбинациям групп
Как 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, который возвращает ровно одно значение и встаёт прямо на место колонки или в 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: как считать нарастающие итоги, скользящие средние и не сломать 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?
WITH … AS — это «именованный временный результат», он же CTE (Common Table Expression). Простыми словами: способ разбить сложный запрос на читаемые шаги, переиспользовать промежуточные расчёты и вообще писать SQL, который потом не противно перечитывать. С таблицами и частыми ошибками.
Несколько CTE в одном SQL-запросе
Несколько CTE через запятую — это способ выстроить запрос «по шагам»: сначала посчитали одно, потом на основе этого второе, потом сложили в финальный результат. Простыми словами: цепочки CTE, переиспользование промежуточных результатов и рекурсивные CTE для работы с иерархиями.
Рекурсивные CTE в SQL: как обходить деревья, цепочки и графы одним запросом
Как устроен 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, использовать EXCLUDED, делать идемпотентные вставки и атомарные счётчики.
MERGE в SQL: INSERT, UPDATE и DELETE в одном операторе
Разбираем оператор 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 и REGEXP_SPLIT_TO_TABLE в PostgreSQL: как разбивать грязные строки по шаблону
REGEXP_SPLIT_TO_ARRAY разбивает строку по regex-разделителю в массив text[]: переменные пробелы, смесь запятой и точки с запятой, пустые элементы по краям и разворот через UNNEST.
TRANSLATE в SQL: как заменять и удалять отдельные символы в строке
TRANSLATE заменяет символы первого набора на символы того же номера во втором, удаляет символы без пары и помогает строить slug, но это не REPLACE.
BTRIM, LTRIM и RTRIM в PostgreSQL: как аккуратно чистить строки по краям
Разбираем BTRIM, LTRIM и RTRIM: как убирать пробелы, нули, слеши и другие символы с краев строки без повреждения середины значения.
format() в PostgreSQL: как собирать строки и безопасный динамический SQL
format() в PostgreSQL собирает строку по шаблону через %s, а %I и %L безопасно подставляют идентификаторы и литералы в динамический SQL вместо хрупкой конкатенации.
`STARTS_WITH` в PostgreSQL: как проверить, что строка начинается с нужного префикса
STARTS_WITH(str, prefix) в PostgreSQL 11+ проверяет начало строки буквально, без экранирования %. Разбираем регистр, индексы text_pattern_ops, NULL и эквиваленты в MySQL и ClickHouse.
ASCII и CHR в PostgreSQL: как получить код символа и собрать символ по коду
ascii() возвращает кодовую точку первого символа, chr() собирает символ по коду; в PostgreSQL оба работают с полным Unicode, а в MySQL и ClickHouse поведение иное.
to_hex в PostgreSQL: как перевести число в шестнадцатеричный вид
Функция to_hex(int) превращает число в hex-строку для цветов, битовых масок и отладки флагов; как сделать обратное преобразование и чем отличаются MySQL и ClickHouse.
AGE в PostgreSQL: как считать возраст, стаж и давность по календарю
AGE возвращает разницу как годы, месяцы и дни, поэтому подходит для возраста и стажа, но не заменяет подсчет точных суток.
DATE_PART в PostgreSQL: как достать час, день недели, неделю или секунды из даты
DATE_PART достает год, месяц, день недели, epoch и другие поля из timestamp или interval, но требует внимания к типам и нумерации.
EXTRACT(EPOCH FROM ...) в PostgreSQL: как получить секунды из даты, времени и интервала
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 в PostgreSQL: текущее время, которое не всегда «текущее»
CURRENT_TIMESTAMP возвращает timestamptz и фиксируется на старте транзакции; разбираем отличие от LOCALTIMESTAMP и clock_timestamp для аудита и DEFAULT.
CURRENT_DATE и CURRENT_TIME в SQL: текущая дата, время и полный момент
CURRENT_DATE, CURRENT_TIME и CURRENT_TIMESTAMP — значения SQL без скобок: дата, время суток с поясом и полный момент. Разбираем типы, фильтры WHERE и DEFAULT.
Арифметика дат в SQL: как складывать даты, интервалы и не путать дни с часами
Как прибавлять дни к date, вычитать даты в число суток и прибавлять interval к timestamp в PostgreSQL, MySQL и ClickHouse.
make_date и make_time в PostgreSQL: как собрать дату и время из отдельных чисел
MAKE_DATE и MAKE_TIME безопасно собирают значения из числовых колонок и сразу показывают ошибки диапазона вместо тихой нормализации.
make_timestamp и make_interval в PostgreSQL: как собирать дату и интервал из чисел
make_timestamp собирает timestamp из чисел года, месяца, дня и времени, а make_interval строит interval из именованных аргументов — без хрупких форматных строк.
AT TIME ZONE в PostgreSQL: как переводить время между часовыми поясами
AT TIME ZONE либо назначает часовой пояс наивному timestamp, либо показывает момент времени в локальной зоне пользователя.
JUSTIFY_* в PostgreSQL: как привести интервалы к понятному виду
JUSTIFY_INTERVAL переносит часы в дни и дни в месяцы, но его 30-дневный месяц не равен календарной логике бизнеса.
DATE_BIN в PostgreSQL: как группировать время по 15 минут, 6 часов и любому удобному шагу
DATE_BIN группирует события в интервалы любой ширины от выбранной точки отсчета, когда DATE_TRUNC слишком груб для аналитики.
OVERLAPS в SQL: как проверить пересечение двух периодов
Как через OVERLAPS проверить, пересекаются ли два периода, и находить накладки в бронированиях и сменах в PostgreSQL.
`timestamptz` и `timestamp` в PostgreSQL: как не перепутать момент времени и часы на стене
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 статьиJSONB @> в PostgreSQL: containment-поиск, вложенные фрагменты и GIN-индексы
Оператор @> проверяет, содержит ли JSONB нужный фрагмент; разберём вложенные объекты, массивы, типы и выбор между GIN и ->>.
ROUND в SQL: как округлять числа, цены и проценты без сюрпризов
ROUND(x, n) округляет до n знаков после запятой; в PostgreSQL двухаргументная форма требует numeric. Разбираем отрицательное n, валютный вывод и поведение ClickHouse.
GIN-индексы для JSONB в PostgreSQL: jsonb_ops, jsonb_path_ops и индексы по выражениям
Разбираем, когда JSONB-фильтрам нужен GIN, чем jsonb_ops отличается от jsonb_path_ops и когда дешевле индекс по выражению.
Составной индекс в SQL: левый префикс, сортировка и INCLUDE
Правильный порядок колонок в составном индексе закрывает фильтр, ORDER BY и index-only scan, а неправильный оставляет плану лишнюю работу.
Sargable WHERE: как писать условия, которые используют индекс
Функция вокруг столбца превращает индекс в декорацию; покажем, как заменить EXTRACT, date(), lower() и LIKE на индексные условия.
ROUND в SQL: как округлять числа и не ловить копейки-призраки
ROUND округляет до ближайшего целого, но половинки и тип double меняют результат; разберём стратегии округления и расчёт денег на numeric.
Что такое CEIL в SQL: округление вверх, страницы и корзины
CEIL отвечает на вопрос «сколько целых единиц нужно»; используйте его для пагинации, упаковки и верхних границ диапазонов.
Удаление из JSONB в PostgreSQL: операторы - и #- простыми словами
Как операторы - и #- удаляют ключи, индексы массивов и вложенные значения из JSONB без пересборки документа в приложении.
jsonb_build_object в PostgreSQL: как собрать JSON прямо в SQL-запросе
Как jsonb_build_object собирает объект из пар ключ-значение, сохраняет типы, строит вложенные ответы и отличается от to_jsonb.
`jsonb_build_array` в PostgreSQL: как собрать JSON-массив прямо в SQL
Как jsonb_build_array собирает позиционный JSON-массив, сохраняет порядок и типы и чем отличается от to_jsonb SQL-массива.
`->` и `->>` в PostgreSQL: как доставать данные из `JSONB`
Как операторы -> и ->> читают поля JSONB, достают элементы массивов, строят цепочки и требуют явного приведения типов.
Что такое ABS в SQL: модуль числа и расстояние без знака
ABS превращает разницу в расстояние: удобно для сверок, поиска отклонений и сравнений с epsilon, но в WHERE есть индексная ловушка.
jsonb_array_length в PostgreSQL: как посчитать элементы в JSONB-массиве и не уронить запрос
Как jsonb_array_length считает элементы массива, почему падает на non-array и как jsonb_typeof защищает фильтры и агрегаты.
jsonb_array_elements в PostgreSQL: как превратить JSONB-массив в строки
jsonb_array_elements раскладывает JSONB-массив на строки, по строке на элемент: фильтрация и джойн по элементам, индекс через WITH ORDINALITY, вариант _text.
EXP и LN в PostgreSQL: зачем логарифмы нужны в SQL-аналитике
Как EXP и LN считают натуральные логарифмы, средние геометрические, темпы роста и требуют строго положительного входа.
`jsonb_agg` в PostgreSQL: как собрать строки в JSON-массив
Как jsonb_agg сворачивает строки в массив JSONB, управляет порядком, фильтрует элементы и требует COALESCE для пустых групп.
Что такое FLOOR в SQL: округление вниз без сюрпризов
FLOOR всегда идёт к меньшему целому, поэтому на отрицательных значениях отличается от TRUNC и влияет на корзины и диапазоны.
UNION и UNION ALL в SQL: как объединять результаты SELECT-запросов
Выберите правильный оператор для склейки выборок: где нужен быстрый UNION ALL, когда оправдан UNION и почему порядок столбцов важнее имён.
GREATEST и LEAST в PostgreSQL: как выбрать большее или меньшее значение внутри строки
GREATEST и LEAST возвращают максимум и минимум столбцов внутри одной строки, зажимают число в диапазон через вложенный вызов и по-разному обрабатывают NULL в PostgreSQL, MySQL и ClickHouse.
Целочисленное деление в SQL: почему 7 / 2 иногда равно 3, а иногда 3.5
Когда оператор / в PostgreSQL отсекает дробь, почему лишний cast превращает 7/2 в 3.5, чем выручает функция div(a, b), как с тем же справляются DIV в MySQL и intDiv в ClickHouse и почему рядом почти всегда стоит MOD.
INTERSECT в SQL: как найти строки, которые есть в обеих выборках
INTERSECT возвращает строки, присутствующие в результатах обоих SELECT; разберём INTERSECT ALL, кратность, NULL, приоритет операторов и замену через EXISTS/JOIN.
EXCEPT в SQL: как найти строки, которые есть в одной выборке, но отсутствуют в другой
EXCEPT вычитает второй набор из первого, помогает искать расхождения и отличается от NOT EXISTS обработкой дублей и NULL.
JSONB ->> в PostgreSQL: как извлечь поле из JSON как текст
Оператор ->> достаёт скаляр из JSONB как text; покажем разницу с ->, приведение типов, NULL для отсутствующих ключей и индексы.
CREATE INDEX CONCURRENTLY: как создать индекс в PostgreSQL без остановки записей
Как построить и удалить индекс на горячей таблице без простоя, почему команда не живёт в транзакции и чем опасен INVALID-индекс.
EXPLAIN ANALYZE BUFFERS: как читать реальный план PostgreSQL
План с ANALYZE показывает фактические строки, loops и буферы; по ним видно, где планировщик ошибся и почему запрос читает лишнее.
SELECT FOR UPDATE: построчные блокировки, очереди и дедлоки в PostgreSQL
SELECT FOR UPDATE защищает чтение-потом-запись от гонок; разберём режимы блокировок, NOWAIT, SKIP LOCKED и порядок захвата строк.
Условный UPDATE: как атомарно проверить условие и изменить данные
Перенесите предусловие внутрь UPDATE, чтобы списания, смены статуса и compare-and-swap не проигрывали гонку между SELECT и записью.
Атомарный счётчик в SQL: почему n = n + 1 безопаснее, чем считать в приложении
Счётчик нельзя увеличивать через read-modify-write; один UPDATE с n = n + 1 сериализует инкременты и сохраняет точность.
GRANT в SQL: привилегии, роли и минимально достаточный доступ
GRANT задаёт реальную границу доступа: права на схемы, таблицы и колонки, членство в ролях и осторожное делегирование через grant option.
REVOKE в SQL: как отзывать права без сюрпризов от PUBLIC и ролей
Отозвать доступ сложнее, чем выдать: проверьте прямые гранты, PUBLIC, членство в ролях и цепочки WITH GRANT OPTION.
CREATE ROLE в PostgreSQL: пользователи, группы и наследование прав
В PostgreSQL роль может быть пользователем или группой; разберём LOGIN/NOLOGIN, INHERIT, SET ROLE и атрибуты уровня кластера.
Read-only роль в PostgreSQL: доступ к данным без права что-то сломать
Соберите роль для BI правильно: USAGE на схему, SELECT на текущие таблицы и default privileges, чтобы будущие таблицы не выпали.
WIDTH_BUCKET в PostgreSQL: как построить гистограмму прямо в SQL
WIDTH_BUCKET раскладывает число по равным по ширине корзинам, ловит выход за границы в корзины 0 и n+1 и строит распределения через GROUP BY.
TRUNC в SQL: как отбросить дробную часть без округления
TRUNC срезает дробную часть, не глядя на следующие цифры; разберём второй аргумент, деньги и отличие от FLOOR на возвратах.
`to_jsonb` в PostgreSQL: как превратить строку таблицы в JSON
Как to_jsonb превращает любое значение, строку или массив в jsonb, сохраняя типы, и чем он умнее json_build_object и старого row_to_json.
SQRT в PostgreSQL: квадратный корень в SQL без сюрпризов
SQRT возвращает квадратный корень: как он ведёт себя в PostgreSQL, почему падает на отрицательном входе и как им считать расстояния и стандартное отклонение.
`SIGN` в SQL: как понять направление изменения числа
Как SIGN возвращает -1, 0 или 1, отделяет направление от величины и помогает классифицировать рост, падение и нулевое изменение.
POWER в PostgreSQL: степени, корни и формулы роста в SQL
POWER(base, exponent) возводит число в степень: степени, корни через дробный показатель 1.0/n, сложный процент и проверка на переполнение.
Что такое MOD в SQL: остаток от деления, чётность и корзины
Остаток от деления делит строки на чётные, когорты и шарды, но отрицательные значения и нулевой делитель требуют внимания.
LOG в PostgreSQL: логарифмы, лог-шкалы и главная ловушка с MySQL
В PostgreSQL LOG(x) — десятичный логарифм, а LOG(b, x) — по любому основанию; разбираем отличие от MySQL и применение логарифмов для шкал и порядков величины.
jsonb_typeof в PostgreSQL: как проверить тип JSON-значения и не уронить запрос
jsonb_typeof отдаёт тип JSON-значения текстом и страхует jsonb_array_length, арифметику и валидацию полуструктурированных данных от падения.
`jsonb_set` в PostgreSQL: как точечно обновлять поля внутри `JSONB`
Как jsonb_set заменяет значение по пути, работает с create_missing, обновляет вложенные поля в UPDATE и чем удаление отличается от правки.
jsonb_pretty в PostgreSQL: как красиво вывести JSONB для чтения и отладки
jsonb_pretty форматирует JSONB с отступами и переносами строк для отладки в psql; разбираем порядок ключей и когда формат включать не стоит.
Операторы #> и #>> в PostgreSQL: как доставать данные из вложенного jsonb
Как #> и #>> читают вложенные значения по text[]-пути, смешивают ключи с индексами и когда вместо них нужен jsonb_path_query.
jsonb_object_keys в PostgreSQL: как получить ключи из JSONB-объекта
jsonb_object_keys разворачивает ключи верхнего уровня JSONB в строки: разведать схему колонки, проверить наличие поля и собрать ключи через array_agg.
Как проверять наличие ключей в jsonb в PostgreSQL: операторы ?, ?| и ?&
Операторы ?, ?| и ?& в jsonb проверяют наличие ключей верхнего уровня, ускоряются GIN-индексом и конфликтуют с плейсхолдерами драйверов.
`jsonb_each` в PostgreSQL: как развернуть JSON-объект в строки
jsonb_each разворачивает JSONB-объект в строки key/value: перебор динамических ключей, фильтрация, агрегация и когда брать jsonb_each_text.
Оператор || для jsonb в PostgreSQL: как быстро объединять JSON-документы
Как оператор || сливает JSONB-объекты, почему правый ключ побеждает, что происходит с массивами и где нужен jsonb_set.
RANDOM в PostgreSQL: как получать случайные строки, числа и выборки без боли
RANDOM() возвращает дробь из [0, 1): как тянуть случайные строки, почему ORDER BY RANDOM() тормозит на масштабе и когда брать TABLESAMPLE, floor и setseed.
NOT EXISTS против NOT IN: как безопасно искать строки, которых нет в другой таблице
Один NULL в подзапросе способен сломать NOT IN; разберём, почему NOT EXISTS обычно безопаснее и когда уместен LEFT JOIN IS NULL.
Частичный индекс в SQL: как ускорить «горячие» запросы и не индексировать лишнее
Как с помощью CREATE INDEX ... WHERE покрыть только активные строки, получить меньший и более быстрый индекс и сделать UNIQUE-ограничение, дружащее с soft-delete.
Как читать EXPLAIN в PostgreSQL и находить причины медленных запросов
Практический разбор плана запроса в PostgreSQL: Seq Scan против Index Scan, оценки против реальности и как поймать недостающий индекс.
Очередь задач в PostgreSQL через FOR UPDATE SKIP LOCKED
Как заставить десяток воркеров безопасно разбирать задачи из таблицы-очереди, не блокируя друг друга — с помощью FOR UPDATE SKIP LOCKED в PostgreSQL.