SQL Ready | Базы Данных
Авторский канал про Базы Данных и SQL Ресурсы, гайды, задачи, шпаргалки. Информация ежедневно пополняется! Автор: @energy_it РКН: https://clck.ru/3QREBc Реклама на бирже: https://telega.in/c/sql_ready
Show more📈 Analytical overview of Telegram channel SQL Ready | Базы Данных
Channel SQL Ready | Базы Данных (@sql_ready) in the Russian language segment is an active participant. Currently, the community unites 15 559 subscribers, ranking 8 396 in the Technologies & Applications category and 43 154 in the Russia region.
📊 Audience metrics and dynamics
Since its creation on невідомо, the project has demonstrated rapid growth, gathering an audience of 15 559 subscribers.
According to the latest data from 11 June, 2026, the channel demonstrates stable activity. Although there has been a change in the number of participants by 56 over the last 30 days and by -9 over the last 24 hours, overall reach remains high.
- Verification status: Not verified
- Engagement rate (ER): The average audience engagement rate is 12.41%. Within the first 24 hours after publication, content typically collects 6.30% reactions from the total number of subscribers.
- Post reach: On average, each post receives 1 931 views. Within the first day, a publication typically gains 980 views.
- Reactions and interaction: The audience actively supports content: the average number of reactions per post is 24.
- Thematic interests: Content is focused on key topics such as sql, строка, user_id, created_at, desc.
📝 Description and content policy
The author describes the resource as a platform for expressing subjective opinions:
“Авторский канал про Базы Данных и SQL
Ресурсы, гайды, задачи, шпаргалки.
Информация ежедневно пополняется!
Автор: @energy_it
РКН: https://clck.ru/3QREBc
Реклама на бирже: https://telega.in/c/sql_ready”
Thanks to the high frequency of updates (latest data received on 12 June, 2026), the channel maintains relevance and a high level of publication reach. Analytics show that the audience actively interacts with content, making it an important point of influence in the Technologies & Applications category.
Оставляю ссылочку: GitHub 📱➡️ SQL Ready | #репозиторий
Оставляю ссылочку: GitHub 📱➡️ SQL Ready | #репозиторий
BETWEEN кажется удобным, но он включает обе границы, из-за чего легко ловятся баги на датах и времени, особенно с timestamp:
WHERE created_at BETWEEN '2025-01-01' AND '2025-01-31'
Такой код пропустит всё, что позже '2025-01-31 00:00:00', и это одна из самых частых, незаметных ошибок в аналитике:
WHERE created_at >= '2025-01-01'
AND created_at < '2025-02-01'
Полуинтервал [start, end) работает предсказуемо для любых типов времени, не ломается на миллисекундах и хорошо ложится на индексы:
WHERE ts >= now()
AND ts < now() + interval '1 day'
🔥 Этот паттерн используют в биллинге, аналитике, логах и любых системах, где важна точность временных границ.
➡️ SQL Ready | #советОставляю ссылочку: GitHub 📱➡️ SQL Ready | #репозиторий
orders(id, customer_id, amount, created_at)
И вот такой запрос:
SELECT * FROM orders LIMIT 10;
Интуитивно хочется думать, что это первые 10 или последние 10. На деле — это просто неопределённые 10 строк в неопределённом порядке.
Без ORDER BY база не обязана возвращать данные в каком-то фиксированном порядке. Сегодня это один набор строк, завтра — другой. Особенно если поменялся план выполнения или появился индекс.
Типичный кейс — хочу последние заказы:
SELECT *
FROM orders
ORDER BY created_at DESC
LIMIT 10;
Уже лучше: теперь это 10 самых новых по created_at.
Но тут есть тонкость — если несколько строк имеют одинаковый created_at, порядок между ними не детерминирован. Иногда это всплывает в самых неожиданных местах (например, в пагинации).
Поэтому обычно добавляют второй критерий:
SELECT *
FROM orders
ORDER BY created_at DESC, id DESC
LIMIT 10;
Если id уникальный — результат становится детерминированным для текущего среза данных. Где это особенно критично: пагинация, API, отчёты, кэш.
Без стабильного порядка начинаются фантомные баги: строки то появляются, то исчезают, то дублируются.
OFFSET и его ограничения:
SELECT *
FROM orders
ORDER BY created_at DESC, id DESC
LIMIT 10 OFFSET 20;
Добавились новые записи — и страницы уже не совпадают с тем, что было секунду назад.
Поэтому в проде чаще используют keyset pagination:
SELECT *
FROM orders
WHERE (created_at, id) < ('2026-01-10', 1050)
ORDER BY created_at DESC, id DESC
LIMIT 10;
Фактически: дай следующие записи после этой точки.
Работает быстрее и ведёт себя предсказуемо при изменениях данных (Важно: синтаксис с (col1, col2) поддерживается не во всех СУБД; универсальный вариант — через OR.)
И ещё частая ошибка:
SELECT *
FROM orders
ORDER BY created_at
LIMIT 1;
Кажется, что это последняя запись, а по факту — самая старая (по умолчанию используется ASC в большинстве СУБД).
🔥 Вся суть: LIMIT отвечает только за количество. Порядок — это всегда ORDER BY. Без составного индекса (created_at, id) такие запросы на больших таблицах начинают ощутимо тормозить.
➡️ SQL Ready | #практикаCREATE STATISTICS s_orders (dependencies)
ON user_id, status
FROM orders;
Extended statistics позволяют оптимизатору учитывать зависимости между колонками, например что у конкретного user_id почти всегда один и тот же status:
ANALYZE orders;
После сбора статистики PostgreSQL начинает правильно оценивать селективность комбинации условий, а не перемножать вероятности как будто они независимы:
EXPLAIN ANALYZE SELECT ...
🔥 Не меняешь код и индексы, но кардинально улучшаешь планы выполнения.
➡️ SQL Ready | #советGRANT даёт пользователю права на таблицу, а ROLLBACK отменяет изменения в рамках транзакции.
На картинке — 5 групп SQL-команд: от определения структуры до управления доступом.
Сохрани, чтобы не забыть!
➡️ SQL Ready | #ресурсCHECK позволяет задать правила, которым обязана соответствовать каждая строка в таблице. Это удобно, когда нужно гарантировать корректные значения без сторонней логики.
Представим, что мы хотим убедиться, что цена товара всегда больше нуля:
CREATE TABLE products (
product_id SERIAL PRIMARY KEY,
name TEXT,
price NUMERIC(10,2),
CHECK (price > 0)
);
Теперь добавим ограничение, чтобы процент скидки был в пределах от 0 до 100:
ALTER TABLE discounts
ADD CONSTRAINT percent_range_chk
CHECK (percentage BETWEEN 0 AND 100);
И создадим таблицу событий, где дата начала всегда должна быть раньше даты окончания:
CREATE TABLE events (
id SERIAL PRIMARY KEY,
starts_at TIMESTAMP,
ends_at TIMESTAMP,
CHECK (starts_at < ends_at)
);
🔥 Но помните, что CHECK проверяет только вставляемые или обновлённые строки. Если вы добавляете ограничение в таблицу с данными, указывайте NOT VALID, чтобы временно обойти проверку.
➡️ SQL Ready | #практикаУзкое место — не мощность сервера, а эффективность кода и архитектуры запросов.Прокачайте скорость для себя и команды - получите бесплатно тренинг «Аналитика без тормозов» от Георгия Семенова, руководителя из Яндекс Вы узнаете: ✅ Методы ускорения запросов и дашбордов, применимые к любой СУБД ✅ Специфические нюансы оптимизации, которые отличают middle от senior. Но это не всё. Мы понимаем: результат дает прокачка всей команды и внедрение знаний в конкретные рабочие задачи. Симулейтив предлагает корпоративное обучение под ключ: ✅Преподаватели-практики из “биг-теха” адаптируют программу под ваши задачи ✅Выгода до 30% при пакетном команды ✅Рамочный договор и помощь с компенсацией Примените знания уже сегодня, а затем внедрите её в работу всего отдела аналитики - чтобы ваши процессы полетели! Забрать тренинг Реклама. ООО "АЙТИ РЕЗЮМЕ". ИНН 4025460134. erid: 2W5zFJpk4QR
• Почему логика обновить + вставить ломается; • Как зафиксировать правило на уровне базы; • Как условный уникальный индекс предотвращает дубликаты.Подход, который убирает класс ошибок с конкурентным доступом и делает данные консистентными независимо от нагрузки. ➡️ SQL Ready | #гайд
sales(id, revenue, orders_count)
Самый очевидный вариант:
SELECT
id,
revenue / orders_count AS avg_order_value
FROM sales;
На первый взгляд всё нормально. Но как только orders_count = 0, начинаются проблемы: в ряде СУБД такой запрос упадёт с ошибкой.
Обычно в таких местах используют NULLIF:
SELECT
id,
revenue / NULLIF(orders_count, 0) AS avg_order_value
FROM sales;
Что здесь происходит: NULLIF(orders_count, 0) вернёт: orders_count, если это не ноль; NULL, если это ноль.
Соответственно: если знаменатель не ноль — деление выполняется как обычно; если знаменатель ноль — получится NULL.
И это как раз правильное поведение. Потому что NULLIF не исправляет данные и не подменяет ноль каким-то удобным значением. Он просто говорит: в этой строке результат не определён.
Иногда после этого пишут так:
SELECT
id,
COALESCE(revenue / NULLIF(orders_count, 0), 0) AS avg_order_value
FROM sales;
Так делать можно, но только если 0 здесь действительно имеет смысл.
Потому что: NULL — значение не определено; 0 — значение определено и равно нулю. Это разные вещи. И подмена одного другим — уже не технический, а смысловой выбор.
Ещё пример:
SELECT
id,
success_count * 100.0 / NULLIF(total_count, 0) AS success_percent
FROM stats;
Почему именно 100.0, а не 100? Чтобы не получить целочисленное деление в тех СУБД, где дробная часть иначе отбросится.
То же самое можно записать и через CASE:
SELECT
id,
CASE
WHEN orders_count = 0 THEN NULL
ELSE revenue / orders_count
END AS avg_order_value
FROM sales;
Это тоже нормальный вариант. Но когда задача именно в защите от деления на ноль, NULLIF обычно короче и читается быстрее.
Ещё момент, который часто путают:
SELECT
SUM(revenue) / NULLIF(SUM(orders_count), 0) AS avg_order_value
FROM sales;
а также:
SELECT
AVG(revenue / NULLIF(orders_count, 0)) AS avg_order_value
FROM sales;
Это разные расчёты. В первом случае — общая выручка делится на общее число заказов. Во втором — считается среднее от построчных значений, причём AVG пропускает NULL.
🔥 Итог простой: NULLIF(x, 0) — приём, который в реальных запросах спасает. Особенно когда хочется не просто чтобы не упало, а чтобы результат оставался корректным по смыслу.
➡️ SQL Ready | #практика
Available now! Telegram Research 2025 — the year's key insights 
