7786
Авторский канал про Базы Данных и SQL Ресурсы, гайды, задачи, шпаргалки. Информация ежедневно пополняется! Автор: @energy_it
✍️ Bilabon — задачи и теория по MySQL!
Это шпаргалка с ключевой теорией и упражнениями: управление БД и таблицами, типы данных, индексы, транзакции и оптимизация запросов. Также приведены практические задачи, позволяющие закрепить знания на примерах реальных предметных областей.
Оставляю ссылочку: GitHub 📱
📂 Напоминалка по SQL — базовые команды и порядок выполнения запроса!
Например, SELECT отвечает за выборку данных, FROM — за указание источника (таблицы), а WHERE позволяет отфильтровать строки по условию.
На картинке — основные операторы SQL, типы JOIN’ов и правильный порядок выполнения запроса внутри СУБД.
Сохрани, чтобы не забыть!
➡️ SQL Ready | #ресурс
💡 SQL Fiddle — онлайн платформа для тестирования SQL без установки БД!
Сервис позволяет писать, запускать и проверять SQL-запросы прямо в браузере. Можно создать схему базы, заполнить тестовыми данными и сразу увидеть результат выполнения, идеально для экспериментов, обучения и разбора задач. Поддерживает разные СУБД (MySQL, PostgreSQL, Oracle, SQL Server и др.), поэтому удобно сравнивать поведение запросов.
📌 Оставляю ссылочку: sqlfiddle.com
➡️ SQL Ready | #сайт
TRUNC(date) — как правильно обрезать дату в Oracle без потери индекса!
В Oracle тип DATE хранит дату и время одновременно. Частая задача — сравнить только по дате, игнорируя время. Многие используют TRUNC(date), но это может сильно ухудшить производительность.
Представим таблицу:
orders(id, created_at DATE)
SELECT *
FROM orders
WHERE TRUNC(created_at) = DATE '2026-02-18';
created_at в основном не используется, и Oracle вынужден вычислять TRUNC для множества строк, что часто приводит к полному сканированию.SELECT *
FROM orders
WHERE created_at >= DATE '2026-02-18'
AND created_at < DATE '2026-02-19';
created_at.TRUNC(date) полезен в SELECT или GROUP BY, когда фильтрация по индексу не критична:SELECT
TRUNC(created_at) AS day,
COUNT(*) AS orders_count
FROM orders
GROUP BY TRUNC(created_at)
ORDER BY day;
TRUNC(created_at), можно создать функциональный индекс:CREATE INDEX idx_orders_created_day
ON orders (TRUNC(created_at));
TRUNC сможет использовать индекс.TRUNC умеет обрезать дату до разных уровней:SELECT
TRUNC(SYSDATE) AS day,
TRUNC(SYSDATE, 'MM') AS month_start,
TRUNC(SYSDATE, 'YYYY') AS year_start
FROM dual;
DATE хранит дату со временем, поэтому = DATE '2026-02-18' не находит все записи за день; функции над колонками мешают индексам.TRUNC — для отображения, агрегации или вместе с функциональным индексом.
Проверка наличия связанных данных!
Когда нужно проверить существование связанных строк, обычный JOIN часто увеличивает результат или заставляет делать DISTINCT, что бьёт по производительности:
SELECT *
FROM orders o
WHERE EXISTS (
SELECT 1 FROM payments p
WHERE p.order_id = o.id
);
EXISTS останавливается на первой найденной строке и не создаёт дубликатов, поэтому обычно работает быстрее и предсказуемее:SELECT *
FROM orders o
WHERE NOT EXISTS (
SELECT 1 FROM payments p
WHERE p.order_id = o.id
);
NOT EXISTS - наиболее корректный способ найти записи без соответствующих связанных данных. NOT IN он корректнее работает при наличии NULL:SELECT *
FROM orders o
LEFT JOIN payments p ON p.order_id = o.id
WHERE p.order_id IS NULL;
LEFT JOIN + IS NULL делает то же самое логически, но чаще требует больше работы оптимизатора и может уступать по производительности на больших объёмах.
LATERAL — коррелированные подзапросы!
Часто бывает нужно для каждой строки основной таблицы взять одну лучшую связанную строку - последнюю, первую, максимальную, минимальную, валидную.
Обычно это делают через оконки, CTE или GROUP BY + JOIN, что сложно читать и часто ломается при расширении логики:
LEFT JOIN LATERAL (...)
ORDER BY created_at DESC
LIMIT 1
ON true
Изоляция рунета ближе, чем ты думаешь
Loading …
██████████████] 99%
🖥 MySQL: работа со строками!Шпаргалка по строковым функциям MySQL для повседневной работы. Разбор приёмов вычисления длины строк, извлечения подстрок, поиска значений, управления регистром и правилами сравнения. Полезно для валидации данных, сортировок, фильтрации, миграций и тонкой настройки запросов без изменения схемы БД.
➡️ SQL Ready | #шпора
NULL и сравнения — почему = и <> с NULL не работают!NULL в SQL — не значение, а его отсутствие. Из-за этого любые обычные сравнения с NULL ведут себя не так, как ожидают, и часто ломают фильтрацию.
Таблица:
users(id, email, deleted_at)
SELECT *
FROM users
WHERE deleted_at = NULL;
deleted_at = NULL
NULL (=, <>, <, >) возвращает UNKNOWN, а WHERE пропускает только TRUE.WHERE deleted_at <> NULL;
IS NULL:SELECT *
FROM users
WHERE deleted_at IS NULL;
SELECT *
FROM users
WHERE deleted_at IS NOT NULL;
IS NULL и IS NOT NULL — всегда возвращают TRUE или FALSE, никогда UNKNOWN.WHERE status = 'active'
AND deleted_at <> '2026-01-01'
deleted_at равен NULL, всё выражение становится UNKNOWN, и строка отбрасывается, даже если status = 'active'.WHERE status = 'active'
AND deleted_at IS NULL
OR:WHERE role = 'admin'
OR deleted_at IS NULL
IS NULL не возвращает UNKNOWN, а значит выражение может стать TRUE.NULL не работают в WHERE; любой UNKNOWN в WHERE — строка отбрасывается. Если строка пропала из результата — первым делом проверяй условия с NULL
NULL и сравнения — почему = и <> с NULL не работают!NULL в SQL — не значение, а его отсутствие. Из-за этого любые обычные сравнения с NULL ведут себя не так, как ожидают, и часто ломают фильтрацию.
Таблица:
users(id, email, deleted_at)
SELECT *
FROM users
WHERE deleted_at = NULL;
deleted_at = NULL
NULL (=, <>, <, >) возвращает UNKNOWN, а WHERE пропускает только TRUE.WHERE deleted_at <> NULL;
IS NULL:SELECT *
FROM users
WHERE deleted_at IS NULL;
SELECT *
FROM users
WHERE deleted_at IS NOT NULL;
IS NULL и IS NOT NULL — всегда возвращают TRUE или FALSE, никогда UNKNOWN.WHERE status = 'active'
AND deleted_at <> '2026-01-01'
deleted_at равен NULL, всё выражение становится UNKNOWN, и строка отбрасывается, даже если status = 'active'.WHERE status = 'active'
AND deleted_at IS NULL
OR:WHERE role = 'admin'
OR deleted_at IS NULL
IS NULL не возвращает UNKNOWN, а значит выражение может стать TRUE.NULL не работают в WHERE; любой UNKNOWN в WHERE — строка отбрасывается. Если строка пропала из результата — первым делом проверяй условия с NULL
📂 Напоминалка для работы с алгоритмами выбора лидера в распределённых системах!
Например, Raft выбирает лидера через голосование, Paxos использует кворум, а Bully Algorithm назначает лидером узел с максимальным ID.
На картинке — 5 базовых алгоритмов leader election, которые используются в распределённых БД и системах координации.
Сохрани, чтобы не забыть!
➡️ SQL Ready | #ресурс
Слили в телеграмм тонны инфы и отсортировали по каналам
🖥 Курсы & GitHub — 1579ГБ
⌨️ Python — 955ГБ
🤒 OSINT — 315ГБ
☁️ Хакинг & ИБ — 756ГБ
🙃 Linux & Bash — 459ГБ
😦 Работа в IT — 778ГБ
🖥 Общий архив — 2346ГБ
➡️ Практические инструкции, курсы, книги и инструменты.
LEFT JOIN и WHERE — классическая ловушка с NULL!LEFT JOIN используют, когда нужно сохранить строки из левой таблицы, даже если в правой нет совпадений. Но одно неверное условие в WHERE — и LEFT JOIN незаметно превращается в INNER JOIN.
Таблицы:
users(id, email)
orders(id, user_id, amount)
SELECT
u.id,
u.email,
o.amount
FROM users u
LEFT JOIN orders o ON o.user_id = u.id;
orders будут NULL — это ожидаемое поведение LEFT JOIN.SELECT
u.id,
u.email,
o.amount
FROM users u
LEFT JOIN orders o ON o.user_id = u.id
WHERE o.amount > 100;
WHERE отфильтровывает строки, где o.amount IS NULL.INNER JOIN.ON:SELECT
u.id,
u.email,
o.amount
FROM users u
LEFT JOIN orders o
ON o.user_id = u.id
AND o.amount > 100;
orders.INNER JOIN:SELECT
u.id,
u.email,
o.amount
FROM users u
JOIN orders o ON o.user_id = u.id
WHERE o.amount > 100;
WHERE применяются после JOIN и могут уничтожить строки с NULL. Условия в ON влияют только на логику связывания таблиц.
❤️ AlgoTree — понятные объяснения алгоритмов, деревьев и графов!
Этот сайт помогает анализировать структуры данных: деревья, графы, обходы и множество другого. Здесь нет решений задач или подготовкой к собеседованиям, упор именно на понимание того, как и почему всё устроено. Материал подается последовательно и концептуально, поэтому хорошо подходит даже новичкам.
📌 Оставляю ссылочку: algotree.org
➡️ SQL Ready | #ресурс
Как получить «последнюю запись на группу»?
Очень частая задача - взять последнюю запись на пользователя, заказ, сущность. Многие делают это с ROW_NUMBER(), хотя Postgres умеет проще:
SELECT DISTINCT ON (user_id) *
FROM orders
ORDER BY user_id, created_at DESC;
DISTINCT ON оставляет первую строку в рамках группы, а порядок задаётся через ORDER BY:ORDER BY user_id, created_at DESC
created_at, лучше явно добавить тай-брейкер:ORDER BY user_id, created_at DESC, id DESC
SELECT *, просто укажите нужные колонки:SELECT DISTINCT ON (user_id)
user_id, id, created_at
FROM orders
ORDER BY user_id, created_at DESC, id DESC;
DISTINCT ON (...) обязаны быть левым префиксом ORDER BY, иначе Postgres выдаст ошибку.ROW_NUMBER(), и при подходящем индексе (user_id, created_at DESC, id DESC) может давать отличный план выполнения.
🖥 Объединяем пересекающиеся интервалы автоматически!
В реальных данных интервалы часто перекрываются или соприкасаются, из-за чего сложно понять фактические периоды непрерывной активности или занятости.
Сегодня в задаче:
• Определим, насколько далеко тянется текущая занятость, отслеживая максимальный конец интервалов;
• Найдём точки разрыва, где начинается новый независимый блок времени;
• Объединим пересечения в итоговые непрерывные диапазоны.
Вычисление временных интервалов между датами!
PostgreSQL умеет возвращать полноценный интервал одной операцией:
now() - created_at
age(), которая учитывает календарь, а не просто секунды:SELECT age(now(), created_at)
FROM orders;
EXTRACT(EPOCH FROM now() - created_at) / 3600
FlowchartAI — это бесплатный AI-генератор блок-схем, который из текста или кода автоматически строит диаграмму. Он анализирует твой ввод (описание процесса/алгоритма или код) и превращает его в визуальную блок-схему, которую можно смотреть прямо в браузере без регистрации.
📌 Оставляю ссылочку: flowchartai.org
➡️ SQL Ready | #ресурс
💡 Отличную статью нашёл на Хабре: «Демобаза 2.0 для PostgreSQL»!
В этой статье:• Показано, как устроена учебная база, приближенная к реальным продакшен-сценариям с миллионами записей;
• Разобрано, как генерируются правдоподобные данные через имитацию работы системы, включая бронирования и жизненный цикл событий;
• Объясняется, какие задачи по SQL, аналитике и производительности можно отрабатывать на такой базе.
🔊 Продолжайте читать на Habr!
👍 TutorialsPoint — сайт с теорий и практикой в одном месте!
Удобный онлайн-редактор, где можно быстро проверить SQL-запросы без установки СУБД и настройки окружения. Встроенные примеры позволяют сразу попробовать SELECT, JOIN, агрегатные функции, подзапросы и другие конструкции на готовых таблицах. Подходит для обучения, практики, подготовки к собесам. Также можно использовать, как мини шпаргалку.
📌 Оставляю ссылочку: tutorialspoint.com
➡️ SQL Ready | #сайт
WHERE vs HAVING — фильтрация строк и фильтрация групп!
В SQL иногда путают WHERE и HAVING, потому что внешне они решают похожую задачу — отфильтровать результат. На практике это два разных этапа выполнения запроса с разной семантикой.
Представим таблицу заказов:
orders(id, customer_id, amount)
SELECT *
FROM orders
WHERE amount > 100;
WHERE применяется до агрегации и фильтрует отдельные строки исходной таблицы.SELECT customer_id, SUM(amount) AS total_amount
FROM orders
WHERE SUM(amount) > 1000
GROUP BY customer_id;
WHERE, потому что на момент применения WHERE агрегатов ещё не существует.HAVING:SELECT customer_id, SUM(amount) AS total_amount
FROM orders
GROUP BY customer_id
HAVING SUM(amount) > 1000;
HAVING применяется после GROUP BY и фильтрует уже сформированные группы.WHERE — фильтрует строки до группировки; GROUP BY — формирует группы; HAVING — фильтрует группы; SELECT — формирует итоговый результат.WHERE в HAVING без необходимости:SELECT customer_id, SUM(amount)
FROM orders
GROUP BY customer_id
HAVING amount > 100;
amount — это поле строки, а HAVING работает с группой.SELECT customer_id, SUM(amount) AS total_amount
FROM orders
WHERE amount > 100
GROUP BY customer_id
HAVING SUM(amount) > 1000;
WHERE отсекает мелкие заказы до агрегации (меньше данных); HAVING проверяет условие на уровне группы.WHERE для фильтрации строк и HAVING — только для условий на агрегаты и группы. Это влияет не только на корректность, но и на производительность запроса
✍️ QOMP — квиз для проверки знаний и закрепления навыков!
Небольшой, но ёмкий квиз, который проверяет логику работы SQL-запросов. Вопросы заставляют подумать: как реально отработает запрос, где скрыта ошибка и почему результат не такой, как ожидаешь. Отлично подходит для самопроверки и подготовки к собеседованиям.
📌 Оставляю ссылочку: qomp.club
➡️ SQL Ready | #ресурс
📂 Напоминалка по типам баз данных!
Например, Relational / SQL базы подходят для строгих транзакций и сложных связей, Time-series — для метрик, логов и мониторинга, а NoSQL — когда важны масштабирование, гибкость схемы и высокая нагрузка.
На картинке — 3 типа баз данных с примерами и их основными особенностями.
Сохрани, чтобы не забыть!
➡️ SQL Ready | #ресурс
Знали, что в SQL можно получить несколько уровней агрегации за один проход по данным?
Частая задача - посчитать метрики сразу на нескольких уровнях: по стране и статусу, только по стране и общий итог. Обычно для этого пишут несколько SELECT и склеивают их UNION ALL:
SELECT country, status, COUNT(*) FROM orders GROUP BY country, status
UNION ALL
SELECT country, NULL, COUNT(*) FROM orders GROUP BY country
UNION ALL
SELECT NULL, NULL, COUNT(*) FROM orders;
GROUPING SETS позволяет описать все нужные уровни агрегации в одном GROUP BY: GROUP BY GROUPING SETS ((country, status), (country), ())
() - это глобальный итог. Колонки, которые не участвуют в текущем уровне, приходят как NULL:(country = NULL, status = NULL)
🎄 Новый год - идеальный момент перезапустить себя.
Не “с понедельника”.
Не “когда будет время”.
А сейчас.
🖥 SCD2 — хранение истории изменений в таблицах!
При прямом UPDATE данные теряют историю: невозможно корректно восстановить состояние сущности на дату или отследить момент изменения.
Сегодня в гайде:
• Как моделировать версионные данные через valid_from / valid_to;
• Как корректно закрывать предыдущую версию и создавать новую;
• Как получать актуальное состояние и исторические срезы без дополнительной логики.
😎 Сodedokode/pasta — теория + задачи на практике!
Репозиторий с понятным и структурированным разбором баз данных на русском языке. Здесь разобраны ключевые концепции SQL для MySQL и PostgreSQL, есть примеры запросов и задачи для самостоятельной работы. Отлично подходит для укрепления базы и подготовки к собеседованиям.
Оставляю ссылочку: GitHub 📱
⚡ Повысить производительность СУБД или сократить расходы на IT-инфраструктуру?
Не нужно выбирать. Selectel расскажет и покажет, как найти баланс на примере собственного сервиса.
Подключайтесь к бесплатному вебинару для тех, кто работает с базами данных
🗓 5 февраля, 12:00
📍 Онлайн
Вы узнаете:
- как работают базы данных на выделенном облачном сервере,
- какие особенности архитектуры позволяют повысить производительность сервиса в 10 раз и получить до 1,5 млн IOPS и 7000 Мб/c в облаке,
- как клиентам Selectel удается экономить до 47% на IT-инфраструктуре.
Регистрируйтесь по ссылке: https://slc.tl/27v33
👉 Чтобы не пропустить новые мероприятия, воркшопы и бесплатные курсы Selectel, подписывайтесь на @selectel_events
Реклама. АО "Селектел". erid:2W5zFJj73Gc
🖥 Ищем пересекающиеся бронирования!
В системах бронирования одна из частых ошибок - это пересечение интервалов, когда один и тот же ресурс оказывается занят сразу несколькими пользователями.
Сегодня в задаче:
• Сравним бронирования одного ресурса между собой, не создавая дубликатов;
• Проверим пересечение временных интервалов с помощью канонического условия;
• Получим список конфликтующих бронирований, которые система должна блокировать.
🖥 Поиск дубликатов и ранжирование данных!Шпаргалка по оконным функциям и агрегатам для нумерации строк, поиска и анализа дубликатов, ранжирования результатов и аккуратного удаления лишних записей. Используется при очистке данных, аналитических запросах, построении рейтингов и подготовке данных к миграциям и отчётности.
➡️ SQL Ready | #шпора