SQL Ready | Базы Данных
Авторский канал про Базы Данных и SQL Ресурсы, гайды, задачи, шпаргалки. Информация ежедневно пополняется! Cотрудничество: @energy_c РКН: https://clck.ru/3QREBc
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 17 741 subscribers, ranking 7 336 in the Technologies & Applications category and 37 136 in the Russia region.
📊 Audience metrics and dynamics
Since its creation on невідомо, the project has demonstrated rapid growth, gathering an audience of 17 741 subscribers.
According to the latest data from 18 October, 2026, the channel demonstrates stable activity. Although there has been a change in the number of participants by 696 over the last 30 days and by 5 over the last 24 hours, overall reach remains high.
- Verification status: Not verified
- Engagement rate (ER): The average audience engagement rate is 12.57%. Within the first 24 hours after publication, content typically collects 6.05% reactions from the total number of subscribers.
- Post reach: On average, each post receives 2 222 views. Within the first day, a publication typically gains 1 069 views.
- Reactions and interaction: The audience actively supports content: the average number of reactions per post is 23.
- Thematic interests: Content is focused on key topics such as sql, строка, users, индекс, user_id.
📝 Description and content policy
The author describes the resource as a platform for expressing subjective opinions:
“Авторский канал про Базы Данных и SQL
Ресурсы, гайды, задачи, шпаргалки.
Информация ежедневно пополняется!
Cотрудничество: @energy_c
РКН: https://clck.ru/3QREBc”
Thanks to the high frequency of updates (latest data received on 19 October, 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.
UNION удаляет дубликаты по всем выбранным колонкам, сравнивая строки целиком, поэтому результат может отличаться от ожиданий.
SELECT message FROM logs_app
UNION
SELECT message FROM logs_system;
Одинаковые message схлопнутся в одну строку, даже если это разные события — ошибки не будет.
UNION ALL не удаляет строки из результата запросов, поэтому почти всегда работает быстрее:
SELECT message FROM logs_app
UNION ALL
SELECT message FROM logs_system;
Для логов полезно явно добавлять источник:
SELECT 'app' AS src, id, message FROM logs_app
UNION ALL
SELECT 'system' AS src, id, message FROM logs_system
ORDER BY src, id;
Пересечение (INTERSECT) в MySQL не поддерживается, альтернатива:
SELECT DISTINCT a.message
FROM logs_app a
WHERE EXISTS (SELECT 1 FROM logs_system s WHERE s.message = a.message)
LIMIT 10;
Если хотите увидеть, какие строки пропадут при UNION из-за совпадений между таблицами, используйте UNION ALL и проверяйте строки, встречающиеся в обоих источниках:
SELECT message, COUNT(*) AS cnt, COUNT(DISTINCT src) AS sources
FROM (
SELECT message, 'app' AS src FROM logs_app
UNION ALL
SELECT message, 'system' AS src FROM logs_system
) t
GROUP BY message
HAVING sources > 1;
🔥 UNION — когда нужна дедупликация, UNION ALL — когда важна каждая строка и производительность.
➡️ SQL Ready | #практикаSkiplist ускоряет поиск в памяти, Hash-индекс даёт доступ за O(1), а B-tree и LSM-дерево оптимизируют работу с диском и записью.
На картинке — 8 структур данных, которые стоит держать под рукой, чтобы понимать, как устроены индексы и хранение в БД.
Сохрани, чтобы не забыть!
➡️ SQL Ready | #ресурсJOIN по колонке, которая логически должна совпадать в обоих наборах:
JOIN table_b b ON a.id = b.id
Выберите только ключи, чтобы исключить лишние проекции и ускорить анализ наборов:
SELECT a.id
Проверьте сами на интерактивном примере:
CREATE TABLE table_a(id int);
CREATE TABLE table_b(id int);
INSERT INTO table_a VALUES (1),(2),(3);
INSERT INTO table_b VALUES (2),(3),(4);
Повторите исходный JOIN, вы увидите только 2,3 как пересечение наборов.
🔥 Пригодится, когда нужно сверить итерации, найти общие сущности перед миграциями и тд.
➡️ SQL Ready | #советПолучаем платную версию:🤩🤩🤩🤩🤩🤩🔐
Оживляем фото, генерим студийную фотосессию с собой 💪
Делаем из нейронки флирт бота влюбляем в себя любую ❤️
Зарабатываем на крипте с помощью прогнозов нейронки 💸
Снимаем цензуру одним промтом🤬
Как сделать из нейронки помощника или друга ✍️
Решаем любую домашку одной фоткой 📸
UPDATE:
WITH c AS (SELECT id FROM products WHERE price < 0 LIMIT 3)
CTE c вернёт проблемные id.
Теперь обновим только найденные строки, не дублируя условие в клиенте:
UPDATE products SET price = 0
Ссылаемся на выборку из CTE, чтобы не рассинхронизировать find/update:
WHERE id IN (SELECT id FROM c);
Попробуйте сами на тестовой таблице:
CREATE TABLE products(id int PRIMARY KEY, price int);
INSERT INTO products VALUES (1,-10),(2,-5),(3,100);
Запустите find+update снова и убедитесь, что исправление точечное и атомарное.
🔥 Экономит время выравнивания таблиц при интеграциях, корректировки классификаторов или миграций и др.
➡️ SQL Ready | #советОставляю ссылочку: GitHub 📱➡️ SQL Ready | #репозиторий
FOR UPDATE SKIP LOCKED
Строки, которые уже залочены, исключаются из выборки немедленно, без ожидания.
Хотите повторить интерактивно? Откройте 2 SQL-сессии:
Сессия A:
BEGIN;
SELECT id FROM jobs WHERE status='queued' FOR UPDATE;
Сессия B (параллельно):
BEGIN;
SELECT id FROM jobs WHERE status='queued' FOR UPDATE SKIP LOCKED LIMIT 1;
B никогда не вернёт строку, залоченную A, и не будет ждать, вы увидите разные результаты в разных сессиях.
🔥 База данных сама может быть механизмом синхронизации, если выборка делается с SKIP LOCKED. Нет двойной обработки, ожиданий и внешних зависимостей.
➡️ SQL Ready | #советTRANSACTION при автокоммите каждый UPDATE фиксируется отдельно — и есть риск получить несогласованное состояние.
Таблицы:
wallet(user_id, balance)
payments(id, user_id, amount, status)
Сценарий: списать баланс и перевести платёж в done.
Если соединение обрывается между запросами:
UPDATE wallet SET balance = balance - 100 WHERE user_id = 7;
-- сбой соединения тут
UPDATE payments SET status = 'done' WHERE id = 55;
Первое изменение уже сохранено, второе — нет. Итог: деньги списаны, платёж не подтверждён.
Правильный подход — транзакция:
BEGIN;
UPDATE wallet SET balance = balance - 100 WHERE user_id = 7;
UPDATE payments SET status = 'done' WHERE id = 55;
COMMIT;
До COMMIT изменения видны только в текущей сессии и не становятся устойчивыми. Если все шаги успешны — фиксируется сразу всё.
Откат при ошибке:
BEGIN;
UPDATE wallet SET balance = balance - 100 WHERE user_id = 7;
UPDATE payments SET status = 'done' WHERE id = 55;
ROLLBACK;
Пока сессия жива, открытая транзакция не откатывается сама по себе и может удерживать блокировки. Автоматический ROLLBACK происходит именно при разрыве соединения или явном откате.
Нюанс для защиты от гонок и повторной обработки:
UPDATE wallet
SET balance = balance - 100
WHERE user_id = 7 AND balance >= 100;
UPDATE payments
SET status = 'done'
WHERE id = 55 AND status = 'pending';
Оба UPDATE выполняем в одной транзакции, затем проверяем rowcount: если любой запрос затронул 0 строк — ROLLBACK и обработка как ошибка.
🔥 SELECT ... FOR UPDATE также работает только в той же транзакции, где будет обновление. Любая операция списания + фиксации платежа = транзакция.
➡️ SQL Ready | #практикаUPDATE может перезаписывать строку, даже если значение не изменилось.
IS DISTINCT FROM сравнивает значения NULL-безопасно и без UNKNOWN:
AND u.name IS DISTINCT FROM 'Alice';
Если name уже Alice — условие ложно, и строка не обновляется вообще.
Это правило можно применить к любым колонкам:
AND u.email IS DISTINCT FROM EXCLUDED.email;
Паттерн остаётся тем же: обновление только при расхождении.
Проверьте сами на тесте:
CREATE TABLE users(id int PRIMARY KEY, name text);
INSERT INTO users VALUES (1, 'Bob');
Запустите 2 раза UPDATE сверху, второй раз таблица не изменится и ничего не запишет.
🔥 UPDATE должен менять только то, что отличается и SQL уже даёт для этого инструменты.
➡️ SQL Ready | #советproducts(id, category, price)
Нужно выбрать самый дорогой товар в каждой категории, но при этом видеть все колонки строки:
SELECT *
FROM (
SELECT
*,
ROW_NUMBER() OVER (PARTITION BY category ORDER BY price DESC, id DESC) AS rn
FROM products
) t
WHERE rn = 1;
PARTITION BY формирует независимые окна для каждой категории.
ROW_NUMBER() нумерует строки внутри каждой партиции, а не по всей таблице.
Если нужны не только первые, а, например, топ-3 в каждой категории:
SELECT id, category, price
FROM (
SELECT
id, category, price,
ROW_NUMBER() OVER (PARTITION BY category ORDER BY price DESC, id DESC) AS rn
FROM products
) t
WHERE rn <= 3
ORDER BY category, price DESC;
Тут важно: без PARTITION BY запрос взял бы топ-3 по всей таблице, а не по категориям.
Оконные функции не требуют GROUP BY, потому что не агрегируют (не схлопывают) строки, а дополняют их аналитическими метками.
Ещё полезный трюк — находить максимум в группе без GROUP BY и JOIN, через коррелированный подзапрос:
SELECT *
FROM products
WHERE price = (
SELECT MAX(price)
FROM products p2
WHERE p2.category = products.category
);
Этот запрос не агрегирует основную таблицу и вернёт несколько строк, если в категории есть товары с одинаковой максимальной ценой (ties).
🔥 Используйте PARTITION BY в оконных функциях, когда логика должна применяться внутри каждой группы независимо, а строки нужно сохранить целиком.
➡️ SQL Ready | #практика