SQL Ready | Базы Данных
前往频道在 Telegram
Авторский канал про Базы Данных и SQL Ресурсы, гайды, задачи, шпаргалки. Информация ежедневно пополняется! Cотрудничество: @energy_c РКН: https://clck.ru/3QREBc
显示更多📈 Telegram 频道 SQL Ready | Базы Данных 的分析概览
频道 SQL Ready | Базы Данных (@sql_ready) 俄语 语言赛道中的 是活跃参与者。目前社区聚集了 17 660 名订阅者,在 技术与应用 类别中位列第 7 358,并在 俄罗斯 地区排名第 37 256 位。
📊 受众指标与增长动态
自 невідомо 创建以来,项目保持高速增长,吸引了 17 660 名订阅者。
根据 16 十月, 2026 的最新数据,频道保持稳定运转。过去 30 天订阅人数变化为 653,过去 24 小时变化为 130,整体触达仍然可观。
- 认证状态: 未认证
- 互动率 (ER): 平均受众互动率为 12.22%。内容发布后 24 小时内通常能获得 6.06% 的反应,占订阅者总量。
- 帖子覆盖: 每篇帖子平均可获得 2 155 次浏览,首日通常累积 1 069 次浏览。
- 互动与反馈: 受众积极参与,单帖平均反应数为 21。
- 主题关注点: 内容集中在 sql, строка, users, индекс, user_id 等核心主题上。
📝 描述与内容策略
作者将该频道定位为表达主观观点的平台:
“Авторский канал про Базы Данных и SQL
Ресурсы, гайды, задачи, шпаргалки.
Информация ежедневно пополняется!
Cотрудничество: @energy_c
РКН: https://clck.ru/3QREBc”
凭借高频更新(最新数据采集于 17 十月, 2026),频道始终保持新鲜度与高覆盖。分析显示受众积极互动,使其成为 技术与应用 类别中的关键影响点。
17 660
订阅者
+13024 小时
+1477 天
+65330 天
帖子存档
17 660
Ускоряйте массовую загрузку через FREEZE!
При загрузке данных в новую таблицу PostgreSQL может сразу пометить строки как замороженные. Для этого у
COPY есть малоизвестная опция FREEZE.
BEGIN;
CREATE TABLE events_import (
id bigint,
payload jsonb
);
COPY events_import
FROM '/data/events.csv'
WITH (FORMAT csv, FREEZE true);
COMMIT;
FREEZE позволяет избежать последующей работы по заморозке загруженных строк. Но есть условие: таблица должна быть создана или очищена через TRUNCATE в текущей подоперации транзакции.
Опция пригодится и при повторной полной загрузке таблицы:
BEGIN;
TRUNCATE events_import;
COPY events_import
FROM '/data/events.csv'
WITH (FORMAT csv, FREEZE true);
COMMIT;
FREEZE не отключает обычные проверки ограничений и не гарантирует ускорения самого импорта. Его преимущество — уменьшение будущей работы VACUUM по заморозке строк.
🔥 Используйте COPY FREEZE при полной загрузке новых или очищенных таблиц, чтобы сократить последующую работу по обслуживанию данных.
➡️ SQL Ready | #совет17 660
Требуются парни и девушки в возрасте 19–40 лет, желающие работать в сфере IT.
Опыт в программировании не нужен.
Завтра запускаем бесплатный онлайн-интенсив по Frontend-разработке, где будем показывать, как разрабатывать сайты и веб-приложения используя ИИ.
За 7 дней обучения без опыта ты:
1. Сделаешь реальный сайт сервиса доставки с нуля;
2. Добавишь JavaScript-логику, расчёты и трекинг;
3. Подключишь карты и маршрут доставки через API;
4. Превратишь сайт в Angular-приложение;
5. Подключишь backend и выложишь проект в продакшен;
6. Научишься использовать ChatGPT и Giga во Frontend-разработке;
7. Узнаешь 9 способов найти первый заказ на фрилансе даже без опыта.
А главное, ты увидишь, что разрабатывать сайты и приложения не так сложно, как кажется. И поймёшь, как тебе развиваться в этой профессии, чтобы уже через пару месяцев зарабатывать от 1000$ на вёрстке сайтов.
👉 Проскочить на интенсив бесплатно
🔥 С 2019 стабильно помогаем с обучением, практикой, зарабатывать на фрилансе и проходить собеседования.
17 660
📂 16 паттернов программирования, которые должен знать каждый разработчик!
Например, Two Pointers помогает эффективно работать с массивами, Sliding Window — находить подмассивы по заданным условиям, а Dynamic Programming — решать сложные задачи через повторное использование результатов подзадач.
На картинке — 16 популярных алгоритмических паттернов и структур данных, которые пригодятся на технических собеседованиях.
Сохрани, чтобы не потерять!
➡️ SQL Ready | #ресурс
17 660
Почему перенос условия из ON в WHERE меняет семантику LEFT JOIN
При использовании
LEFT JOIN расположение предиката определяет не только состав результата, но и возможность сохранить строки левой таблицы без соответствий. Предикаты в ON участвуют в поиске совпадений, тогда как WHERE фильтрует результат соединения.
Рассмотрим запрос, который должен возвращать всех пользователей и количество их завершённых заказов:
SELECT
u.id,
COUNT(o.id) AS completed_orders
FROM users u
LEFT JOIN orders o
ON o.user_id = u.id
WHERE o.status = 'completed'
GROUP BY u.id;
Этот запрос исключает пользователей без завершённых заказов. Предикат o.status = 'completed' является null-rejecting: он не может вернуть TRUE, когда o.status содержит NULL. Поэтому строки, дополненные NULL при внешнем соединении, отбрасываются.
Для сохранения всех пользователей ограничение на статус необходимо включить в условие соединения:
SELECT
u.id,
COUNT(o.id) AS completed_orders
FROM users u
LEFT JOIN orders o
ON o.user_id = u.id
AND o.status = 'completed'
GROUP BY u.id;
Теперь пользователь без завершённых заказов остаётся в результате с количеством 0. Здесь принципиально использование COUNT(o.id): агрегат игнорирует NULL, тогда как COUNT(*) учитывает и строку, созданную внешним соединением при отсутствии совпадений.
В PostgreSQL аналогичную задачу можно решить через агрегатный FILTER, сохранив соединение со всеми заказами:
SELECT
u.id,
COUNT(o.id) FILTER (
WHERE o.status = 'completed'
) AS completed_orders
FROM users u
LEFT JOIN orders o
ON o.user_id = u.id
GROUP BY u.id;
Различие между этими вариантами становится существенным при вычислении нескольких агрегатов. FILTER позволяет применять независимые условия к разным агрегатам без повторного соединения таблиц:
SELECT
u.id,
COUNT(o.id) FILTER (
WHERE o.status = 'completed'
) AS completed_orders,
COUNT(o.id) FILTER (
WHERE o.status = 'pending'
) AS pending_orders
FROM users u
LEFT JOIN orders o
ON o.user_id = u.id
GROUP BY u.id;
Есть и важное следствие для оптимизатора PostgreSQL. Если условие в WHERE исключает все строки с NULL со стороны правой таблицы, внешнее соединение в некоторых случаях может быть преобразовано во внутреннее. Такое преобразование сохраняет семантику исходного запроса, но не исправляет ошибочно выбранную логику фильтрации.
Проверить фактический план выполнения можно через EXPLAIN:
EXPLAIN (ANALYZE, BUFFERS)
SELECT
u.id,
COUNT(o.id)
FROM users u
LEFT JOIN orders o
ON o.user_id = u.id
WHERE o.status = 'completed'
GROUP BY u.id;
В плане может появиться Hash Join вместо Hash Left Join или другой тип внутреннего соединения. Конкретный алгоритм зависит от статистики, индексов и оценок стоимости, поэтому наличие LEFT JOIN в sql не гарантирует сохранение внешнего соединения в физическом плане.
🔥 Перенос предиката между ON и WHERE при внешнем соединении — семантическое преобразование, а не просто изменение записи sql. Null-rejecting предикаты могут устранять строки без совпадений и создавать условия для упрощения LEFT JOIN до INNER JOIN оптимизатором.
➡️ SQL Ready | #практика17 660
⚡️ В сети начали массово сливать IT-курсы и книги известных онлайн школ
Вот отсортированная база с тонной материала (постепенно пополняется):
(363 видео, 87 книги) — Python
(117 видео, 53 книги) — ВАЙБКОД
(174 видео, 91 книги) — DevOps
(415 видео, 68 книги) — Frontend
(137 видео, 93 книги) — DS/ML
(143 видео, 33 книги) — ИБ/Хакинг
(352 видео, 89 книги) — С/С++/C
(343 видео, 87 книги) — Java/QA
(176 видео, 32 книги) — Git/Linux
(167 видео, 53 книги) — PHP/1С
(227 видео, 83 книги) — SQL/БД
(114 видео, 77 книги) — Сисадмин
(107 видео, 43 книги) — BA/SA
(181 видео, 32 книги) — Go/Rust
(167 видео, 43 книги) — Kotlin/Swift
(112 видео, 24 книги) — Flutter
(113 видео, 82 книги) — GameDev
(183 видео, 37 книги) — Дизайн
(136 видео, 33 книги) — PM/HR
Скачивать ничего не нужно — все выложили в Telegram
17 660
👍 Интересная статья лежит на Хабре: «За пределами EXPLAIN: как увидеть выполнение запроса вживую в распределённой СУБД»!
В этой статье:
• Узнаете, почему EXPLAIN не всегда помогает понять причины медленного выполнения SQL-запросов;
• Разберёте, как pg_query_state позволяет отслеживать выполнение запросов в Apache Cloudberry в реальном времени;
• Посмотрите, как архитектура с Go-агентами и сервисом YAGPCC помогает собирать метрики с множества узлов без перегрузки координатора.
🔊 Продолжай читать на Habr!➡️ SQL Ready | #статья
17 660
Переносите строки без промежуточной выборки!
Обычно архивирование делают в два этапа: сначала копируют записи, затем удаляют исходные. В PostgreSQL можно связать эти действия через
DELETE ... RETURNING.
-- Удаляем строки и сразу получаем их содержимое
DELETE FROM events
WHERE created_at < DATE '2025-01-01'
RETURNING id, user_id, payload, created_at;
А теперь используем возвращённые строки как источник для вставки:
WITH moved AS (
DELETE FROM events
WHERE created_at < DATE '2025-01-01'
RETURNING id, user_id, payload, created_at
)
INSERT INTO events_archive (
id, user_id, payload, created_at
)
SELECT id, user_id, payload, created_at
FROM moved;
Всё выполняется одним оператором SQL. Если вставка в архив завершится ошибкой, удаление тоже откатится.
При этом можно преобразовать данные перед архивированием:
WITH moved AS (
DELETE FROM events
WHERE created_at < DATE '2025-01-01'
RETURNING id, payload, created_at
)
INSERT INTO events_archive (id, payload, archived_at)
SELECT id, payload, now()
FROM moved;
🔥 DELETE ... RETURNING внутри WITH позволяет переносить строки между таблицами одним атомарным запросом, без отдельного чтения и передачи данных через приложение.
➡️ SQL Ready | #совет17 660
Требуются 7 человек, чтобы помогали собирать чат-ботов для бизнеса по блокам, как лего.
Стоит попробовать, если хочешь:
✅ ЗП: от 5000-9000₽ за 1-2 вечера.
✅ Занятость: 3–4 часа в день.
✅ Свободный график.
Опыт в разработке не требуется.
Всё, что нужно для старта — запустить обучение
👉@pautov_techspec_bot
И пройти инструктаж.
17 660
📂 Шпаргалка по Eventual Consistency в распределённых системах!
Например, Event-Driven обеспечивает асинхронное распространение изменений между сервисами, а CQRS позволяет разделять операции чтения и записи с независимым обновлением моделей данных.
На картинке — 4 архитектурных подхода, которые помогают управлять согласованностью данных, снижать связанность компонентов и масштабировать распределённые системы.
Сохрани, чтобы не потерять!
➡️ SQL Ready | #ресурс
17 660
Почему BETWEEN может незаметно исключать данные при фильтрации по датам!
При работе с временными диапазонами часто используют
BETWEEN. Но если колонка хранит дату вместе со временем, такой фильтр может возвращать не все ожидаемые записи.
Допустим, есть таблица заказов:
CREATE TABLE orders (
id BIGINT PRIMARY KEY,
created_at TIMESTAMP NOT NULL,
amount DECIMAL(12, 2)
);
Нужно получить заказы за сентябрь 2026 года. На первый взгляд подходит запрос:
SELECT *
FROM orders
WHERE created_at BETWEEN
TIMESTAMP '2026-09-01 00:00:00'
AND TIMESTAMP '2026-09-30 00:00:00';
Однако BETWEEN включает обе границы диапазона и эквивалентен сочетанию >= и <=. Поэтому запрос вернёт записи с 1 сентября по начало 30 сентября, но исключит все заказы, созданные позднее полуночи последнего дня месяца.
Например, запись со временем 2026-09-30 15:30:00 не попадёт в результат. Иногда верхнюю границу пытаются исправить вручную:
WHERE created_at BETWEEN
TIMESTAMP '2026-09-01 00:00:00'
AND TIMESTAMP '2026-09-30 23:59:59';
Но это тоже ненадёжный вариант. Если колонка поддерживает дробные доли секунды, запись 2026-09-30 23:59:59.500 окажется за пределами диапазона.
Для временных интервалов практичнее использовать полуоткрытый диапазон:
SELECT *
FROM orders
WHERE created_at >= TIMESTAMP '2026-09-01 00:00:00'
AND created_at < TIMESTAMP '2026-10-01 00:00:00';
Такой запрос включает все значения за сентябрь независимо от точности хранения времени и исключает записи следующего месяца.
Ещё одно преимущество — соседние интервалы не пересекаются. Например, при последовательной обработке данных можно использовать:
WHERE created_at >= :date_from
AND created_at < :date_to;
При условии, что следующая выборка начинается с предыдущего date_to, каждая запись на границе интервалов попадёт ровно в один диапазон.
Такой подход также хорошо сочетается с обычным B-tree индексом:
CREATE INDEX idx_orders_created_at
ON orders (created_at);
Поскольку фильтрация выполняется непосредственно по индексируемой колонке, оптимизатор может использовать диапазонное сканирование индекса. При использовании типов с часовыми поясами границы необходимо задавать в соответствии с нужной временной зоной, особенно если речь идёт о календарных днях.
🔥 Для фильтрации по временным интервалам условия >= и < обычно надёжнее, чем BETWEEN. Полуоткрытые диапазоны не зависят от точности TIMESTAMP, не пересекаются на границах и удобны для отчётности, пакетной обработки и инкрементальной загрузки данных.
➡️ SQL Ready | #практика17 660
🔴В 2025 году Россияне заработали 5,3 млрд рублей на арбитраже криптовалют
По данным Минфин 32% граждан покинули своё место работы поскольку уже в первый месяц смогли заработать 250 000 рублей, а через 2-3 месяца с легкостью вышли на семизначные числа.
Самое смешное, что лишь 8% россиян что-то слышали об этой профессии хотя все инструкции бесплатно лежат на канале Арбитраж Криптовалют
Там объясняют, как имея телефон и доступ в интернет заработать свои первые $3000. Причём разжёвывают так доступно, что поймёт даже ребенок. Кстати, на канале сегодня вышла новая рабочая связка!
Ссылка для входа — https://t.me/+gL6CZ_b93PBhZGM6
17 660
😎 SQLinfo — русскоязычный справочник по SQL!
Сайт с учебными и справочными материалами по SQL и работе с реляционными базами данных. Подойдёт для изучения основных конструкций языка, понимания принципов построения запросов и повторения теории. Ресурс пригодится начинающим аналитикам и разработчикам, а также тем, кому нужен дополнительный справочник по SQL во время обучения или работы с базами данных.
📌 Оставляю ссылочку: sqlinfo.ru
➡️ SQL Ready | #сайт
17 660
+4
🖥 Oracle - ограничение количества строк и выборка Top-N!
Получение первых N строк с FETCH FIRST, постраничная выборка с FETCH NEXT и OFFSET, включение строк с одинаковыми значениями сортировки через WITH TIES, ограничение результата в процентах с PERCENT, использование ROWNUM, а также нумерация и ранжирование с ROW_NUMBER() и DENSE_RANK().
➡️ SQL Ready | #шпора17 660
Обновляйте несколько колонок одним подзапросом!
Вместо нескольких одинаковых подзапросов:
UPDATE orders o
SET customer_name = (
SELECT name FROM customers WHERE id = o.customer_id
),
customer_email = (
SELECT email FROM customers WHERE id = o.customer_id
);
можно написать:
-- Один подзапрос сразу для нескольких колонок
UPDATE orders o
SET (customer_name, customer_email) = (
SELECT c.name, c.email
FROM customers c
WHERE c.id = o.customer_id
);
Особенно удобно, когда вычисления сложнее:
UPDATE accounts a
SET (last_payment_at, total_paid) = (
SELECT max(p.created_at),
sum(p.amount)
FROM payments p
WHERE p.account_id = a.id
);
Не нужно дублировать условия и поддерживать несколько почти одинаковых подзапросов.
🔥 SET (a, b, ...) = (SELECT ...) позволяет одним подзапросом вычислить сразу несколько новых значений строки и заметно сокращает повторяющийся SQL.
➡️ SQL Ready | #совет17 660
❤️ sqlite-postgres-cours — большой практический курс по базам данных!
Материал ведёт от первых SQL-запросов и проектирования схем до индексов, транзакций, оптимизации и работы с БД из Python через SQLAlchemy и Alembic. Особенно полезно, что SQLite и PostgreSQL изучаются параллельно: автор показывает различия между ними, типичные ошибки и ситуации, где выбор СУБД имеет значение.
Оставляю ссылочку: GitHub 📱➡️ SQL Ready | #репозиторий
17 660
Почему UNIQUE допускает несколько NULL в PostgreSQL!
Ограничение
UNIQUE гарантирует уникальность значений, но для NULL в PostgreSQL действует отдельная семантика. По умолчанию два NULL считаются различными при проверке уникальности, поэтому ограничение не запрещает несколько строк с неопределённым значением:
CREATE TABLE users (
id BIGINT PRIMARY KEY,
email TEXT UNIQUE
);
Повторное определённое значение email нарушит ограничение уникальности.
INSERT INTO users (id, email)
VALUES (1, 'user@example.com');
INSERT INTO users (id, email)
VALUES (2, 'user@example.com');
При использовании NULL те же правила не применяются: несколько строк успешно проходят проверку ограничения.
INSERT INTO users (id, email)
VALUES
(3, NULL),
(4, NULL),
(5, NULL);
Особенно важно учитывать это поведение в составных ключах, где один из столбцов может быть неопределённым:
CREATE TABLE contacts (
id BIGINT PRIMARY KEY,
company_id BIGINT NOT NULL,
external_id TEXT,
UNIQUE (company_id, external_id)
);
Одинаковые определённые значения (company_id, external_id) конфликтуют, но несколько комбинаций (10, NULL) по умолчанию допустимы:
INSERT INTO contacts (id, company_id, external_id)
VALUES
(1, 10, NULL),
(2, 10, NULL);
Начиная с PostgreSQL 15 это поведение можно изменить через NULLS NOT DISTINCT. В таком ограничении NULL считаются неразличимыми при проверке уникальности:
CREATE TABLE contacts_strict (
id BIGINT PRIMARY KEY,
company_id BIGINT NOT NULL,
external_id TEXT,
UNIQUE NULLS NOT DISTINCT (company_id, external_id)
);
Теперь сохранить две строки с одной комбинацией (10, NULL) нельзя: вторая вставка завершится нарушением уникальности.
INSERT INTO contacts_strict (id, company_id, external_id)
VALUES (1, 10, NULL);
INSERT INTO contacts_strict (id, company_id, external_id)
VALUES (2, 10, NULL);
Та же семантика поддерживается уникальными индексами, поэтому правило можно выразить непосредственно на уровне индекса.
CREATE UNIQUE INDEX uq_contacts_company_external
ON contacts (company_id, external_id)
NULLS NOT DISTINCT;
NULLS NOT DISTINCT не эквивалентен NOT NULL. NOT NULL полностью запрещает отсутствие значения, тогда как NULLS NOT DISTINCT разрешает NULL, но включает его в контроль уникальности.
CREATE TABLE identifiers (
id BIGINT PRIMARY KEY,
external_id TEXT,
UNIQUE NULLS NOT DISTINCT (external_id)
);
В такой таблице может существовать одна строка с external_id IS NULL, но вторая аналогичная строка уже нарушит ограничение.
🔥 UNIQUE в PostgreSQL по умолчанию допускает несколько NULL. Если отсутствие значения также должно быть уникальным состоянием, начиная с PostgreSQL 15 это можно явно зафиксировать через NULLS NOT DISTINCT.
➡️ SQL Ready | #практика17 660
📂 Шпаргалка по паттернам распределённых систем!
Например, Replication повышает доступность и отказоустойчивость за счёт хранения копий данных на нескольких узлах, а Sharding позволяет горизонтально масштабировать систему, распределяя данные между независимыми шардами.
Эти паттерны помогают решать основные задачи распределённых систем: масштабирование, отказоустойчивость, распределение данных, асинхронное взаимодействие и согласованность.
Сохрани, чтобы не потерять!
➡️ SQL Ready | #ресурс
17 660
Проверяйте связи с учётом периода!
В PostgreSQL 18 связь может учитывать ещё и период его действия.
WITHOUT OVERLAPS не даст создать пересекающиеся периоды для одного product_id. По сути PostgreSQL сам обеспечивает проверку пересечения диапазонов.
А теперь интересная часть:
CREATE TABLE discounts (
product_id bigint,
valid_at daterange,
FOREIGN KEY (
product_id,
PERIOD valid_at
)
REFERENCES prices (
product_id,
PERIOD valid_at
)
);
Период скидки должен быть покрыт соответствующими периодами родительской таблицы. Причём покрытие может обеспечиваться несколькими соседними строками, а не обязательно одной.
Например, такую логику больше не обязательно проверять вручную перед записью:
INSERT INTO discounts
VALUES (
42,
'[2026-05-01,2026-05-15)'::daterange
);
🔥 В PostgreSQL 18 PERIOD позволяет проверять временные связи обычным FOREIGN KEY — без триггеров и ручных проверок.
➡️ SQL Ready | #совет17 660
⚡️5 фундаментальных курсов по ИБ по цене одного
Это предложение для тех, кто готов войти в новую профессию прямо сейчас!
🔥Пакет курсов за 50 000 ₽ вместо 250 000 ₽:
▪️ Linux CyberPunk - обычная цена 49 500 ₽ (+ Курс идет с официальным дипломом системного администратора!)
▪️ SQL для хакера - обычная цена 15 000 ₽
▪️ HackerPoint - обычная цена ~70 000 ₽
▪️ HackerPoint (Blue vs Red Team) - обычная цена 43 500 ₽
▪️ AI-помощники на Python - обычная цена 71 500 ₽
Вы экономите 200 000 ₽ и получаете полную базу: от работы с терминалом и базами данных до разработки ИИ-агентов и взлома систем.
🔒 Квота: набор на программу ограничен по количеству мест.
🦔Отправь промокод
SQLready в чат с менеджером, чтобы закрепить за собой скидку и узнать подробности:
👉@cyacademy_support17 660
👍 Устройство PostgreSQL — подробная документация на русском языке!
Материалы посвящены не написанию SQL-запросов, а архитектуре СУБД и внутренним механизмам обработки и хранения данных. Подробно рассматриваются физическая структура базы данных, системные каталоги, управление транзакциями, блокировки, WAL и др.
📌 Оставляю ссылочку: database.diasoft.ru
➡️ SQL Ready | #ресурс
