SEQUENCE (MySQL 8.0.29+) — современная альтернатива AUTO_INCREMENT
💡 Зачем знать
🔹 На собеседованиях всё чаще спрашивают: «Чем SEQUENCE отличается от AUTO_INCREMENT и зачем он нужен?»
🔹 В проде помогает, когда один источник чисел требуется сразу нескольким таблицам или когда нельзя допускать длинной блокировки PRIMARY KEY.
1️⃣ Что такое SEQUENCE?
Это отдельный объект в схеме, хранящий текущее значение счётчика.
🔹 Не привязан к конкретной таблице.
🔹 Умеет шаг ( INCREMENT ), начальное значение (START).
🔹 Получить число можно в любом запросе: NEXT VALUE FOR seq_name.
2️⃣ Вставка чисел в таблицу
Получаем уникальный id без AUTO_INCREMENT в самой таблице.
3️⃣ Один счётчик — много таблиц
Нужно, чтобы tickets и invoices шли в общей нумерации? Просто используйте ту же последовательность:
4️⃣ Дополнительные возможности
5️⃣ Сравнение с AUTO_INCREMENT 🤔
🔹 Объект:
– SEQUENCE — отдельный объект в схеме
– AUTO_INCREMENT — жёстко привязан к таблице
🔹Один счётчик для нескольких таблиц:
– SEQUENCE — да, можно использовать в любой таблице
– AUTO_INCREMENT — нет, только внутри своей таблицы
🔹Задать старт / шаг:
– SEQUENCE — гибко: START WITH, INCREMENT BY для каждой последовательности
– AUTO_INCREMENT — глобальные AI_OFFSET / AI_INCREMENT, меньше контроля
🔹Сброс счётчика:
– SEQUENCE —
– AUTO_INCREMENT —
✅ Итог
SEQUENCE = гибкий, «шарящийся» счётчик, который:
🔹Позволяет одной командой нумеровать разные таблицы.
🔹Даёт точный контроль над шагом и стартом.
💡 Зачем знать
🔹 На собеседованиях всё чаще спрашивают: «Чем SEQUENCE отличается от AUTO_INCREMENT и зачем он нужен?»
🔹 В проде помогает, когда один источник чисел требуется сразу нескольким таблицам или когда нельзя допускать длинной блокировки PRIMARY KEY.
1️⃣ Что такое SEQUENCE?
Это отдельный объект в схеме, хранящий текущее значение счётчика.
🔹 Не привязан к конкретной таблице.
🔹 Умеет шаг ( INCREMENT ), начальное значение (START).
🔹 Получить число можно в любом запросе: NEXT VALUE FOR seq_name.
-- создаём последовательность с шага 1, стартуем с 10 000
CREATE SEQUENCE ticket_seq
START WITH 10000
INCREMENT BY 1;
2️⃣ Вставка чисел в таблицу
INSERT INTO tickets (id, user_id, created_at)
VALUES (NEXT VALUE FOR ticket_seq, 42, NOW());
Получаем уникальный id без AUTO_INCREMENT в самой таблице.
3️⃣ Один счётчик — много таблиц
Нужно, чтобы tickets и invoices шли в общей нумерации? Просто используйте ту же последовательность:
INSERT INTO invoices (id, total)
VALUES (NEXT VALUE FOR ticket_seq, 199.00);
4️⃣ Дополнительные возможности
-- увеличить шаг
ALTER SEQUENCE ticket_seq
INCREMENT BY 10;
-- обнулить (осторожно!)
ALTER SEQUENCE ticket_seq
RESTART WITH 50000;
-- посмотреть текущее значение
SELECT LAST_VALUE
FROM INFORMATION_SCHEMA.SEQUENCES
WHERE SEQUENCE_NAME = 'ticket_seq';
5️⃣ Сравнение с AUTO_INCREMENT 🤔
🔹 Объект:
– SEQUENCE — отдельный объект в схеме
– AUTO_INCREMENT — жёстко привязан к таблице
🔹Один счётчик для нескольких таблиц:
– SEQUENCE — да, можно использовать в любой таблице
– AUTO_INCREMENT — нет, только внутри своей таблицы
🔹Задать старт / шаг:
– SEQUENCE — гибко: START WITH, INCREMENT BY для каждой последовательности
– AUTO_INCREMENT — глобальные AI_OFFSET / AI_INCREMENT, меньше контроля
🔹Сброс счётчика:
– SEQUENCE —
ALTER SEQUENCE … RESTART WITH n – AUTO_INCREMENT —
ALTER TABLE … AUTO_INCREMENT = n (только вверх от MAX(id))✅ Итог
SEQUENCE = гибкий, «шарящийся» счётчик, который:
🔹Позволяет одной командой нумеровать разные таблицы.
🔹Даёт точный контроль над шагом и стартом.
🔥12❤5👍3
SUBSTRING() / LEFT() / RIGHT() — извлекаем части строки ✂️
❗ Зачем нужно
Чистка и разбор данных — частая задача аналитика. Извлечь код страны из телефона, отделить год из даты в тексте, взять первые 3 буквы артикулы — всё это делается прямо в SQL, без кода на стороне приложения.
1️⃣ SUBSTRING() — получить подстроку
2️⃣ LEFT(str, N) — «первые N символов»
3️⃣ RIGHT(str, N) — «последние N символов»
💡 Практический пример: разбираем телефон
⚠️ Подводные камни
🔹 Нумерация с 1: первый символ — позиция 1, а не 0.
🔹 NULL → NULL: любое из функций вернёт NULL, если аргумент NULL — учитывайте в отчётах.
✅ Итог
🔹SUBSTRING — универсальный нож: позиция + длина.
🔹LEFT / RIGHT — быстрый способ взять начало или конец строки.
❗ Зачем нужно
Чистка и разбор данных — частая задача аналитика. Извлечь код страны из телефона, отделить год из даты в тексте, взять первые 3 буквы артикулы — всё это делается прямо в SQL, без кода на стороне приложения.
1️⃣ SUBSTRING() — получить подстроку
-- с 3-й позиции длиной 4 символа
SELECT SUBSTRING('ABCDEF', 3, 4);
-- результат: 'CDEF'
-- начиная с 2-го символа до конца
SELECT SUBSTRING('123456', 2);
-- результат: '23456'
-- отрицательный индекс = отсчёт от конца
SELECT SUBSTRING('hello', -2);
-- результат: 'lo’
2️⃣ LEFT(str, N) — «первые N символов»
SELECT LEFT('8901234567', 2);
-- '89' (код страны)
3️⃣ RIGHT(str, N) — «последние N символов»
SELECT RIGHT('2025-04-30', 2);
-- '30' (день)
💡 Практический пример: разбираем телефон
SELECT
phone,
LEFT(phone, 2) AS country_code,
-- первые 2 цифры
SUBSTRING(phone, 3, 3) AS city_code,
-- далее 3 цифры
RIGHT(phone, 4) AS last_digits
-- последние 4
FROM contacts;
⚠️ Подводные камни
🔹 Нумерация с 1: первый символ — позиция 1, а не 0.
🔹 NULL → NULL: любое из функций вернёт NULL, если аргумент NULL — учитывайте в отчётах.
✅ Итог
🔹SUBSTRING — универсальный нож: позиция + длина.
🔹LEFT / RIGHT — быстрый способ взять начало или конец строки.
👍21❤10🔥1👌1
DATE_ADD / DATE_SUB — прибавляем дни, месяцы, годы 📅
❗ Зачем знать
Практически каждый отчёт или запрос «за последние N дней» использует именно эти функции. Умение правильно прибавлять/вычитать интервалы избавит от ошибок с високосными годами и разной длиной месяцев.
1️⃣ Синтаксис
unit бывает: SECOND, MINUTE, HOUR, DAY, WEEK, MONTH, YEAR и их комбинации (например, DAY_MICROSECOND).
2️⃣ Простые примеры
3️⃣ Кейс: отчёт «за последние 30 дней»
👉 CURDATE() = 00:00:00 текущего дня, поэтому попадут 30 «полных» дней.
4️⃣ Прибавляем месяцы правильно
DATE_ADD учитывает разную длину месяцев и високосные годы:
⚠️ Подводные камни
1. Точность NOW(): если нужен только день без времени — используйте CURDATE().
2. Интервалы с недельной гранулярностью: INTERVAL 1 WEEK = 7 дней, не календарная неделя.
❗ Зачем знать
Практически каждый отчёт или запрос «за последние N дней» использует именно эти функции. Умение правильно прибавлять/вычитать интервалы избавит от ошибок с високосными годами и разной длиной месяцев.
1️⃣ Синтаксис
DATE_ADD(date, INTERVAL N unit)
DATE_SUB(date, INTERVAL N unit)
unit бывает: SECOND, MINUTE, HOUR, DAY, WEEK, MONTH, YEAR и их комбинации (например, DAY_MICROSECOND).
2️⃣ Простые примеры
-- дата через 7 дней
SELECT DATE_ADD('2025-05-01', INTERVAL 7 DAY); -- 2025-05-08
-- месяц назад
SELECT DATE_SUB(NOW(), INTERVAL 1 MONTH);
-- +2 часа к текущему времени
SELECT DATE_ADD(NOW(), INTERVAL 2 HOUR);
3️⃣ Кейс: отчёт «за последние 30 дней»
SELECT *
FROM sales
WHERE sale_date >= DATE_SUB(CURDATE(), INTERVAL 30 DAY);
👉 CURDATE() = 00:00:00 текущего дня, поэтому попадут 30 «полных» дней.
4️⃣ Прибавляем месяцы правильно
DATE_ADD учитывает разную длину месяцев и високосные годы:
-- 31 января + 1 месяц → 28 февраля (или 29 в високосный год)
SELECT DATE_ADD('2024-01-31', INTERVAL 1 MONTH); -- 2024-02-29
⚠️ Подводные камни
1. Точность NOW(): если нужен только день без времени — используйте CURDATE().
2. Интервалы с недельной гранулярностью: INTERVAL 1 WEEK = 7 дней, не календарная неделя.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤18🔥10👍4
ELT() и FIELD() — превращаем числовой код в текст без JOIN 🏷️
❓ Зачем нужно
Частый кейс: в таблице хранится числовой статус (1 = “pending”, 2 = “done”, 3 = “failed”).
Обычно делают JOIN с маленьким справочником, но MySQL умеет отдать текст прямо в SELECT — скомпилируем «карманный словарь» функциями FIELD() + ELT().
1️⃣ FIELD(needle, list…) — возвращает позицию элемента
2️⃣ ELT(index, list…) — берёт элемент по номеру
💡 Объединяем: число → позиция → текст
🔹 FIELD находит позицию status_code в списке кодов,
🔹 ELT вытаскивает строку из второго списка той же длины.
3️⃣ Удобный вариант через CASE?
Да, но ELT/FIELD короче, особенно для 5-10 значений.
4️⃣ Подводные камни ⚠️
🔹 Если FIELD вернёт 0 (код не найден) — ELT() даст NULL.
🔹Порядок важен: списки в FIELD и ELT должны совпадать по длине и позиции.
✅ Итог
🔹FIELD() находит позицию кода, ELT() возвращает строку по этой позиции.
🔹Для 3-5 статусов — самый быстрый способ «раскрасить» отчёт без JOIN и CASE.
❓ Зачем нужно
Частый кейс: в таблице хранится числовой статус (1 = “pending”, 2 = “done”, 3 = “failed”).
Обычно делают JOIN с маленьким справочником, но MySQL умеет отдать текст прямо в SELECT — скомпилируем «карманный словарь» функциями FIELD() + ELT().
1️⃣ FIELD(needle, list…) — возвращает позицию элемента
SELECT FIELD(3, 1,2,3,4);
-- Результат: 3
SELECT FIELD('b', 'a','b','c');
-- Результат: 2
2️⃣ ELT(index, list…) — берёт элемент по номеру
SELECT ELT(3, 'pending','done','failed','unknown');
-- Результат: 'failed'
💡 Объединяем: число → позиция → текст
SELECT
order_id,
status_code,
ELT(
FIELD(status_code, 1,2,3,4),
'pending','in_progress','done','failed'
) AS status_text
FROM orders;
🔹 FIELD находит позицию status_code в списке кодов,
🔹 ELT вытаскивает строку из второго списка той же длины.
3️⃣ Удобный вариант через CASE?
Да, но ELT/FIELD короче, особенно для 5-10 значений.
-- аналог на CASE (длиннее)
CASE status_code
WHEN 1 THEN 'pending'
WHEN 2 THEN 'in_progress'
WHEN 3 THEN 'done'
WHEN 4 THEN 'failed'
ELSE 'unknown'
END
4️⃣ Подводные камни ⚠️
🔹 Если FIELD вернёт 0 (код не найден) — ELT() даст NULL.
🔹Порядок важен: списки в FIELD и ELT должны совпадать по длине и позиции.
✅ Итог
🔹FIELD() находит позицию кода, ELT() возвращает строку по этой позиции.
🔹Для 3-5 статусов — самый быстрый способ «раскрасить» отчёт без JOIN и CASE.
🔥22❤8👍4🥰1🙏1
🎉 PostgreSQL теперь с нами! 🐘🎉
Мы расширили движок курса — добавили полную поддержку PostgreSQL.
Теперь все уроки, задачи и автотесты работают как на MySQL, так и на PostgreSQL. Выбирайте любимый диалект — знание SQL теперь прокачивается вдвойне!🚀
Что нового:
1️⃣ Двойной режим — переключайтесь между MySQL ↔ PostgreSQL в один клик.
2️⃣ Все практические задачи проверяются в обоих СУБД, а значит больше гибкости и реальной пользы.
3️⃣ Обновлённые подсказки и примеры с учётом синтаксиса Postgres.
💡 Базовый контент и задания по-прежнему бесплатны.
Спасибо, что растёте вместе с SQL Academy. Теперь на MySQL и PostgreSQL! 💙
Мы расширили движок курса — добавили полную поддержку PostgreSQL.
Теперь все уроки, задачи и автотесты работают как на MySQL, так и на PostgreSQL. Выбирайте любимый диалект — знание SQL теперь прокачивается вдвойне!
Что нового:
1️⃣ Двойной режим — переключайтесь между MySQL ↔ PostgreSQL в один клик.
2️⃣ Все практические задачи проверяются в обоих СУБД, а значит больше гибкости и реальной пользы.
3️⃣ Обновлённые подсказки и примеры с учётом синтаксиса Postgres.
💡 Базовый контент и задания по-прежнему бесплатны.
Спасибо, что растёте вместе с SQL Academy. Теперь на MySQL и PostgreSQL! 💙
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥123👍33❤20
UUID() и UUID_SHORT() — генерируем уникальный ID без сервера приложений 🎲
❗Зачем знать
🔹Иногда нужно создать уникальный первичный ключ на стороне БД, а не приложения.
1️⃣ UUID() — стандартный 128-битный идентификатор
🔹36 символов (32 шестн. + 4 дефисa).
🔹Практически нулевая вероятность коллизии.
🔹Минусы: длинная строка → индекс ~4× крупнее, хуже кэшируется.
2️⃣ UUID_SHORT() — компактный 64-битный вариант
🔹Возвращает BIGINT UNSIGNED (до 18 цифр).
🔹Формируется как: (server_id << 48) + (unix_ts << 24) + increment.
🔹Удобен для числовых PK 👉 индекс меньше, быстрее сортировка.
🔹Риск коллизии есть при одинаковом server_id (на реплике проверьте server_id!).
3️⃣ Практический пример: таблица заказов
✅ Итог
🔹UUID() — гарантированная уникальность, но тяжёлый индекс.
🔹UUID_SHORT() — компактный числовой ID, если контролируете server_id.
🔹Оба способа позволяют генерировать ключ прямо в MySQL без внешнего сервиса или кода приложения.
❗Зачем знать
🔹Иногда нужно создать уникальный первичный ключ на стороне БД, а не приложения.
1️⃣ UUID() — стандартный 128-битный идентификатор
SELECT UUID();
-- '550e8400-e29b-41d4-a716-446655440000'
🔹36 символов (32 шестн. + 4 дефисa).
🔹Практически нулевая вероятность коллизии.
🔹Минусы: длинная строка → индекс ~4× крупнее, хуже кэшируется.
2️⃣ UUID_SHORT() — компактный 64-битный вариант
SELECT UUID_SHORT();
-- 281474976710661
🔹Возвращает BIGINT UNSIGNED (до 18 цифр).
🔹Формируется как: (server_id << 48) + (unix_ts << 24) + increment.
🔹Удобен для числовых PK 👉 индекс меньше, быстрее сортировка.
🔹Риск коллизии есть при одинаковом server_id (на реплике проверьте server_id!).
3️⃣ Практический пример: таблица заказов
CREATE TABLE orders (
id CHAR(36) DEFAULT (UUID()) PRIMARY KEY,
user_id INT,
total DECIMAL(10,2)
);
✅ Итог
🔹UUID() — гарантированная уникальность, но тяжёлый индекс.
🔹UUID_SHORT() — компактный числовой ID, если контролируете server_id.
🔹Оба способа позволяют генерировать ключ прямо в MySQL без внешнего сервиса или кода приложения.
❤20👍5
Задача из собеседования (Cian, middle): считаем, сколько раз издавалось произведение 📚
Схема:
🔹Books(id, title) — произведение
🔹BookEditions(id, book_id, publish_year, pages) — издание произведения
🔹BookCopies(id, edition_id, inventory_num) — экземпляр издания
🎯 Формулировка
Найти произведения, которые издавались более 5 раз. Вывести только название произведения (title).
🧪 Сначала решите сами!
Откройте задачу и попробуйте написать запрос без подсказок:
👉 https://sql-academy.org/ru/trainer/tasks/125
— Разбор ——
Как подойти шаг за шагом:
1️⃣ Что нужно посчитать?
Количество изданий на каждое произведение → считаем строки в BookEditions по book_id.
2️⃣ Где лежит название?
В Books. Значит, к агрегату нужно присоединить Books по Books.id = BookEditions.book_id.
3️⃣ По чему группировать?
По уникальному идентификатору книги (и для вывода — по названию): GROUP BY b.id, b.title.
4️⃣ Как отфильтровать только те, у кого >5 изданий?
Через HAVING, потому что фильтруем по агрегату (COUNT).
Правильный ответ
На что обратить внимание❗️
🔹Группируем по b.id, b.title, а не только по b.title: два разных произведения могут теоретически иметь одинаковое название; по id безопаснее.
А если в условии скрыт нюанс «издавалось в разные годы»?
Иногда собеседующий подразумевает уникальные годы издания. Тогда используйте COUNT(DISTINCT e.publish_year)
Схема:
🔹Books(id, title) — произведение
🔹BookEditions(id, book_id, publish_year, pages) — издание произведения
🔹BookCopies(id, edition_id, inventory_num) — экземпляр издания
🎯 Формулировка
Найти произведения, которые издавались более 5 раз. Вывести только название произведения (title).
🧪 Сначала решите сами!
Откройте задачу и попробуйте написать запрос без подсказок:
👉 https://sql-academy.org/ru/trainer/tasks/125
— Разбор ——
Как подойти шаг за шагом:
1️⃣ Что нужно посчитать?
Количество изданий на каждое произведение → считаем строки в BookEditions по book_id.
2️⃣ Где лежит название?
В Books. Значит, к агрегату нужно присоединить Books по Books.id = BookEditions.book_id.
3️⃣ По чему группировать?
По уникальному идентификатору книги (и для вывода — по названию): GROUP BY b.id, b.title.
4️⃣ Как отфильтровать только те, у кого >5 изданий?
Через HAVING, потому что фильтруем по агрегату (COUNT).
Правильный ответ
SELECT b.title
FROM BookEditions e
JOIN Books b ON b.id = e.book_id
GROUP BY b.id, b.title
HAVING COUNT(e.id) > 5;
На что обратить внимание
🔹Группируем по b.id, b.title, а не только по b.title: два разных произведения могут теоретически иметь одинаковое название; по id безопаснее.
А если в условии скрыт нюанс «издавалось в разные годы»?
Иногда собеседующий подразумевает уникальные годы издания. Тогда используйте COUNT(DISTINCT e.publish_year)
SELECT b.title
FROM BookEditions e
JOIN Books b ON b.id = e.book_id
GROUP BY b.id, b.title
HAVING COUNT(DISTINCT e.publish_year) > 5;
Please open Telegram to view this post
VIEW IN TELEGRAM
👍36🔥10❤9👏2👌1
Вы когда-нибудь задумывались, как правильно вычислить возраст человека в SQL?
🚫 Неправильный подход:
SELECT YEAR(NOW()) - YEAR('2003-07-03 14:10:26');
Проблема такого подхода в том, что он не учитывает был ли день рождения у данного человека в этом году или ещё нет. То есть, если на момент запроса уже наступило 3-е июля (07-03), то человек отпраздновал свой день рождения и ему уже 21 лет, иначе ему по-прежнему 20 года. Разница функций YEAR тут будет бесполезна — в обоих случаях она даст 21 лет.
SELECT FLOOR(DATEDIFF(NOW(), '2003-07-03 14:10:26') / 365);
Это лучше, но всё же не совсем точно из-за наличия високосных годов. 📆
✅ Правильный подход с TIMESTAMPDIFF:
TIMESTAMPDIFF(YEAR, '2003-07-03 14:10:26', NOW());
Используя функцию TIMESTAMPDIFF, мы получаем точную разницу в годах между двумя датами, учитывая все нюансы календаря! 🎯
Так что, когда дело доходит до вычисления возраста, доверяйте TIMESTAMPDIFF — и ваши расчёты будут точны как никогда! 🚀💡
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥47👍17❤9👏1
Деньги в MySQL: DECIMAL против FLOAT 💸
❗️Почему это важно
В финансах «копейка рубль бережёт»: ошибка 0.01 в одной транзакции, умноженная на тысячи строк, ломает отчёты и бухгалтерию.
Главный выбор — где хранить деньги: в DECIMAL или FLOAT?
1️⃣ Короткий ответ
🔹 Для сумм, цен, налогов — используйте DECIMAL(precision, scale).
🔹FLOAT/DOUBLE — приблизительные числа (двойичные), для денег не подходят.
2️⃣ Что такое DECIMAL и FLOAT?
🔹 DECIMAL(p, s) — точные десятичные числа.
Хранит каждую цифру (до 65 знаков, обычно s=2 или 4).
🔹 FLOAT/DOUBLE — числа с плавающей запятой в двоичной форме (IEEE 754).
Быстрые, но дают «хвосты» 0.1000000000001.
Пример проблемы с FLOAT:
Так же, но с DECIMAL:
3️⃣ Как выбрать размер DECIMAL
Типовой набор:
🔹DECIMAL(19,4) — для сумм и цен (4 знака после запятой хватает для НДС/комиссий).
🔹DECIMAL(10,2) — для розничных цен в «валютах с 2 знаками».
4️⃣ Альтернатива: хранить в «копейках»
Иногда суммы хранят как INT в минимальных единицах (центы/копейки).
Плюсы: быстрые индексы, чёткие сравнения.
Минусы: нужна дисциплина преобразований (делить/умножать на 100), разные валюты ≠ одинаковая точность.
5️⃣ Мини-резюме
🔹 Для денег — только DECIMAL (или INT в минимальных единицах).
🔹 Выберите подходящую точность (часто DECIMAL(19,4)).
🔹 Не складывайте «яблоки и апельсины»: валюты и точности должны быть явными.
❗️Почему это важно
В финансах «копейка рубль бережёт»: ошибка 0.01 в одной транзакции, умноженная на тысячи строк, ломает отчёты и бухгалтерию.
Главный выбор — где хранить деньги: в DECIMAL или FLOAT?
1️⃣ Короткий ответ
🔹 Для сумм, цен, налогов — используйте DECIMAL(precision, scale).
🔹FLOAT/DOUBLE — приблизительные числа (двойичные), для денег не подходят.
2️⃣ Что такое DECIMAL и FLOAT?
🔹 DECIMAL(p, s) — точные десятичные числа.
Хранит каждую цифру (до 65 знаков, обычно s=2 или 4).
🔹 FLOAT/DOUBLE — числа с плавающей запятой в двоичной форме (IEEE 754).
Быстрые, но дают «хвосты» 0.1000000000001.
Пример проблемы с FLOAT:
CREATE TEMPORARY TABLE t_f (a FLOAT, b FLOAT);
INSERT INTO t_f VALUES (0.1, 0.2);
SELECT a + b AS sum_val FROM t_f;
-- sum_val может быть 0.3000000119...
Так же, но с DECIMAL:
CREATE TEMPORARY TABLE t_d (a DECIMAL(10,2), b DECIMAL(10,2));
INSERT INTO t_d VALUES (0.10, 0.20);
SELECT a + b AS sum_val FROM t_d;
-- sum_val = 0.30
3️⃣ Как выбрать размер DECIMAL
Типовой набор:
🔹DECIMAL(19,4) — для сумм и цен (4 знака после запятой хватает для НДС/комиссий).
🔹DECIMAL(10,2) — для розничных цен в «валютах с 2 знаками».
4️⃣ Альтернатива: хранить в «копейках»
Иногда суммы хранят как INT в минимальных единицах (центы/копейки).
Плюсы: быстрые индексы, чёткие сравнения.
Минусы: нужна дисциплина преобразований (делить/умножать на 100), разные валюты ≠ одинаковая точность.
5️⃣ Мини-резюме
🔹 Для денег — только DECIMAL (или INT в минимальных единицах).
🔹 Выберите подходящую точность (часто DECIMAL(19,4)).
🔹 Не складывайте «яблоки и апельсины»: валюты и точности должны быть явными.
10❤24👍10🔥6
Please open Telegram to view this post
VIEW IN TELEGRAM
👍67❤14🔥14
Бэкап vs снапшот vs реплика — простое объяснение
Зачем это знать?
В реальной работе регулярно случается одно из трёх: сервер падает, кто-то удаляет данные, выходит неудачное обновление.
Спасают три разных инструмента — бэкап, снапшот и реплика. Они дополняют, а не заменяют друг друга.
Три понятия «на пальцах»
💾 Бэкап (backup)
Это отдельная копия данных, из которой можно развернуть базу заново — даже на другом сервере, через день/неделю.
📸 Снапшот (snapshot)
Это «моментальный снимок» диска/тома в текущем состоянии (LVM/ZFS/EBS и т.п.).
🔹Создаётся быстро, удобно откатиться перед апдейтом.
🔹Хранится на том же хранилище → если диск/массив сломается, снимок пропадёт вместе с ним.
🪞 Реплика (replication)
Это вторая копия базы, которая почти в реальном времени «повторяет» изменения с основной.
🔹Нужна для отказоустойчивости и масштабирования чтения.
🔹Если на мастер попала ошибка/удаление, она уйдёт и на реплику.
Что решает каждый инструмент
Бэкап → «машина времени»
🔹Восстановить состояние за конкретный день/время.
🔹Долгое хранение (архив), юридические требования.
Снапшот → «быстрый откат»
🔹Перед деплоем/миграцией: если что-то пошло не так — откат за минуты.
🔹Клонирование окружения для тестов.
Реплика → «всегда доступно»
🔹Быстро переключиться при падении мастера (failover).
🔹Разгрузить чтение (направить часть трафика на реплику).
Риски и подводные камни ⚠️
Бэкап
🔹«Бэкап есть» не значит «восстановится» — обязательны регулярные тесты восстановления.
🔹Нельзя хранить единственную копию рядом с базой; нужна отдельная площадка и шифрование.
Снапшот
🔹Хранится на том же хранилище → общая точка отказа.
Реплика
🔹Может отставать (лаг) — отчёты «сейчас» иногда смотрят на прошлое.
Практические рекомендации
Минимум для проекта
1️⃣ Ежедневный бэкап (полный или инкрементальный) → хранить вне сервера + шифровать.
2️⃣ Раз в неделю — проверка восстановления на тестовом стенде (restore-drill).
3️⃣ Перед любым рискованным обновлением — снапшот тома.
Зачем это знать?
В реальной работе регулярно случается одно из трёх: сервер падает, кто-то удаляет данные, выходит неудачное обновление.
Спасают три разных инструмента — бэкап, снапшот и реплика. Они дополняют, а не заменяют друг друга.
Три понятия «на пальцах»
💾 Бэкап (backup)
Это отдельная копия данных, из которой можно развернуть базу заново — даже на другом сервере, через день/неделю.
📸 Снапшот (snapshot)
Это «моментальный снимок» диска/тома в текущем состоянии (LVM/ZFS/EBS и т.п.).
🔹Создаётся быстро, удобно откатиться перед апдейтом.
🔹Хранится на том же хранилище → если диск/массив сломается, снимок пропадёт вместе с ним.
🪞 Реплика (replication)
Это вторая копия базы, которая почти в реальном времени «повторяет» изменения с основной.
🔹Нужна для отказоустойчивости и масштабирования чтения.
🔹Если на мастер попала ошибка/удаление, она уйдёт и на реплику.
Что решает каждый инструмент
Бэкап → «машина времени»
🔹Восстановить состояние за конкретный день/время.
🔹Долгое хранение (архив), юридические требования.
Снапшот → «быстрый откат»
🔹Перед деплоем/миграцией: если что-то пошло не так — откат за минуты.
🔹Клонирование окружения для тестов.
Реплика → «всегда доступно»
🔹Быстро переключиться при падении мастера (failover).
🔹Разгрузить чтение (направить часть трафика на реплику).
Риски и подводные камни ⚠️
Бэкап
🔹«Бэкап есть» не значит «восстановится» — обязательны регулярные тесты восстановления.
🔹Нельзя хранить единственную копию рядом с базой; нужна отдельная площадка и шифрование.
Снапшот
🔹Хранится на том же хранилище → общая точка отказа.
Реплика
🔹Может отставать (лаг) — отчёты «сейчас» иногда смотрят на прошлое.
Практические рекомендации
Минимум для проекта
1️⃣ Ежедневный бэкап (полный или инкрементальный) → хранить вне сервера + шифровать.
2️⃣ Раз в неделю — проверка восстановления на тестовом стенде (restore-drill).
3️⃣ Перед любым рискованным обновлением — снапшот тома.
👍23❤7👌4👏2
Триггеры в MySQL 🚀
Триггеры в MySQL — это специальные процедуры, которые автоматически выполняются в ответ на определённые события внутри таблиц базы данных. Они срабатывают при выполнении операций вставки (INSERT), обновления (UPDATE) или удаления (DELETE) данных.
Для чего нужны триггеры🔍
Триггеры используются для автоматизации выполнения задач в базе данных, что помогает обеспечить целостность данных. Например, они могут автоматически обновлять или проверять данные при изменении таблицы, запускать расчёты или создавать журнал изменений (логирование операций).
Создание триггера 🆕
Создать триггер можно с помощью команды CREATE TRIGGER. Например, триггер, который будет автоматически устанавливать текущую дату и время в поле last_updated при обновлении строки в таблице users:
Удаление триггера ❌
Удалить триггер можно с помощью команды DROP TRIGGER. Например:
Полезный пример использования ℹ️
Предположим, в базе данных есть таблица orders с полями id, total и updated_at. Можно создать триггер, который будет обновлять updated_at каждый раз, когда меняется сумма заказа (total):
Этот триггер помогает отслеживать момент последнего изменения суммы заказа, что может быть полезно для аудита изменений или для обновления связанных систем, например, систем бухгалтерского учета.
Триггеры в MySQL — это специальные процедуры, которые автоматически выполняются в ответ на определённые события внутри таблиц базы данных. Они срабатывают при выполнении операций вставки (INSERT), обновления (UPDATE) или удаления (DELETE) данных.
Для чего нужны триггеры
Триггеры используются для автоматизации выполнения задач в базе данных, что помогает обеспечить целостность данных. Например, они могут автоматически обновлять или проверять данные при изменении таблицы, запускать расчёты или создавать журнал изменений (логирование операций).
Создание триггера 🆕
Создать триггер можно с помощью команды CREATE TRIGGER. Например, триггер, который будет автоматически устанавливать текущую дату и время в поле last_updated при обновлении строки в таблице users:
CREATE TRIGGER before_user_update
BEFORE UPDATE ON users
FOR EACH ROW
SET NEW.last_updated = NOW();
Удаление триггера ❌
Удалить триггер можно с помощью команды DROP TRIGGER. Например:
DROP TRIGGER before_user_update;
Полезный пример использования ℹ️
Предположим, в базе данных есть таблица orders с полями id, total и updated_at. Можно создать триггер, который будет обновлять updated_at каждый раз, когда меняется сумма заказа (total):
CREATE TRIGGER update_order_timestamp
BEFORE UPDATE ON orders
FOR EACH ROW
WHEN (OLD.total <> NEW.total)
BEGIN
SET NEW.updated_at = CURRENT_TIMESTAMP;
END;
Этот триггер помогает отслеживать момент последнего изменения суммы заказа, что может быть полезно для аудита изменений или для обновления связанных систем, например, систем бухгалтерского учета.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍25❤8🔥8
Мини-квиз по дате и времени в MySQL
1️⃣ Вопрос 1: Что вернёт запрос?
a) 2024/16/08 21:15
b) 16/08/2024 21:15
c) 2024/08/16 21:15
d) Ошибка парсинга
Правильный ответ:c) 2024/08/16 21:15
2️⃣ Вопрос 2: Какой результат вернёт функция LAST_DAY?
a) 2024-02-28
b) 2024-02-29
c) 2024-03-01
d) NULL
Правильный ответ:b) 2024-02-29
3️⃣ Вопрос 3: Чему равна разница в минутах?
a) 90
b) 95
c) 120
d) 155
Правильный ответ:b) 95
4️⃣ Вопрос 4: Что произойдёт при добавлении интервала, если пересекается полночь?
a) 2024-08-16 25:00:00
b) 2024-08-17 00:00:00
c) 2024-08-17 01:00:00
d) 2024-08-16 23:02:00
Правильный ответ:c) 2024-08-17 01:00:00
1️⃣ Вопрос 1: Что вернёт запрос?
SELECT DATE_FORMAT(
STR_TO_DATE('16-08-2024 21:15', '%d-%m-%Y %H:%i'),
'%Y/%m/%d %H:%i'
);
a) 2024/16/08 21:15
b) 16/08/2024 21:15
c) 2024/08/16 21:15
d) Ошибка парсинга
Правильный ответ:
2️⃣ Вопрос 2: Какой результат вернёт функция LAST_DAY?
SELECT LAST_DAY('2024-02-10');
a) 2024-02-28
b) 2024-02-29
c) 2024-03-01
d) NULL
Правильный ответ:
3️⃣ Вопрос 3: Чему равна разница в минутах?
SELECT TIMESTAMPDIFF(
MINUTE,
'2024-08-16 08:30:00',
'2024-08-16 10:05:00'
);
a) 90
b) 95
c) 120
d) 155
Правильный ответ:
4️⃣ Вопрос 4: Что произойдёт при добавлении интервала, если пересекается полночь?
SELECT TIMESTAMP('2024-08-16', '23:00:00') + INTERVAL 2 HOUR;
a) 2024-08-16 25:00:00
b) 2024-08-17 00:00:00
c) 2024-08-17 01:00:00
d) 2024-08-16 23:02:00
Правильный ответ:
🔥34❤11👍11
Мини-квиз
1️⃣ Вопрос 1: Что гарантирует LEFT JOIN?
a) Вернутся только клиенты с заказами
b) Вернутся все заказы, даже без клиентов
c) Вернутся все клиенты, даже если у них нет заказов
d) Дубликаты строк будут удалены
Правильный ответ:c) Вернутся все клиенты, даже если у них нет заказов
2️⃣ Вопрос 2: Что фильтрует группы после агрегирования?
a) WHERE cnt > 5
b) HAVING cnt > 5
c) ORDER BY cnt > 5
d) WINDOW cnt > 5
Правильный ответ:b) HAVING cnt > 5
3️⃣ Вопрос 3: Какой запрос лучше всего использует составной индекс (department, salary)?
a) WHERE salary > 1000
b) WHERE department = 'IT' AND salary > 1000
c) WHERE department LIKE '%IT%'
d) ORDER BY salary
Правильный ответ: b) WHERE department = 'IT' AND salary > 1000
1️⃣ Вопрос 1: Что гарантирует LEFT JOIN?
SELECT c.id, o.id
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.id;
a) Вернутся только клиенты с заказами
b) Вернутся все заказы, даже без клиентов
c) Вернутся все клиенты, даже если у них нет заказов
d) Дубликаты строк будут удалены
Правильный ответ:
2️⃣ Вопрос 2: Что фильтрует группы после агрегирования?
SELECT department, COUNT(*) AS cnt
FROM employees
GROUP BY department
-- ?
a) WHERE cnt > 5
b) HAVING cnt > 5
c) ORDER BY cnt > 5
d) WINDOW cnt > 5
Правильный ответ:
3️⃣ Вопрос 3: Какой запрос лучше всего использует составной индекс (department, salary)?
a) WHERE salary > 1000
b) WHERE department = 'IT' AND salary > 1000
c) WHERE department LIKE '%IT%'
d) ORDER BY salary
Правильный ответ:
👍29🔥10❤7👌3
Триггеры в PostgreSQL ⚡️
Зачем они нужны?
Триггеры помогают базе сама выполнять рутину: обновлять метки времени, писать журнал изменений, проверять данные. Это экономит код в приложении и снижает ошибки.
Что такое триггер
Триггер — это правило «когда случится X, сделай Y».
🔹 Время: BEFORE (до операции) или AFTER (после).
🔹Событие: INSERT / UPDATE / DELETE.
🔹Уровень:
— FOR EACH ROW — для каждой затронутой строки;
— FOR EACH STATEMENT — один раз на весь запрос.
Важно: в PostgreSQL триггер всегда вызывает функцию (обычно на PL/pgSQL).
Мини-пример: авто-обновление `updated_at` при любом UPDATE
Полезно знать 🧠
🔹Временно отключить/включить:
ALTER TABLE users DISABLE TRIGGER set_updated_at;
ALTER TABLE users ENABLE TRIGGER set_updated_at;
🔹Удалить триггер:
DROP TRIGGER set_updated_at ON users;
🔹Если несколько триггеров одного типа — они срабатывают по алфавиту имён.
Давайте им понятные префиксы (t10_…, t20_…).
Где новички чаще всего ошибаются ⚠️
1️⃣ «Скрытая магия»: непонятно, что меняет данные.
Решение — документируйте триггеры и давайте им говорящие имена.
2️⃣ Массовые операции: FOR EACH ROW на миллионах строк может замедлить UPDATE. Если возможно — переносите часть логики в периодические задачи или используйте FOR EACH STATEMENT.
Зачем они нужны?
Триггеры помогают базе сама выполнять рутину: обновлять метки времени, писать журнал изменений, проверять данные. Это экономит код в приложении и снижает ошибки.
Что такое триггер
Триггер — это правило «когда случится X, сделай Y».
🔹 Время: BEFORE (до операции) или AFTER (после).
🔹Событие: INSERT / UPDATE / DELETE.
🔹Уровень:
— FOR EACH ROW — для каждой затронутой строки;
— FOR EACH STATEMENT — один раз на весь запрос.
Важно: в PostgreSQL триггер всегда вызывает функцию (обычно на PL/pgSQL).
Мини-пример: авто-обновление `updated_at` при любом UPDATE
-- 1) Добавим столбец с текущим временем по умолчанию
ALTER TABLE users
ADD COLUMN updated_at timestamptz NOT NULL DEFAULT now();
-- 2) Функция, которую будет вызывать триггер
CREATE OR REPLACE FUNCTION trg_set_updated_at() RETURNS trigger
LANGUAGE plpgsql AS $$
BEGIN
-- записываем текущее время
NEW.updated_at := now();
-- возвращаем изменённую строку
RETURN NEW;
END$$;
-- 3) Сам триггер: срабатывает перед UPDATE каждой строки
CREATE TRIGGER set_updated_at
BEFORE UPDATE ON users
FOR EACH ROW
EXECUTE FUNCTION trg_set_updated_at();
Полезно знать 🧠
🔹Временно отключить/включить:
ALTER TABLE users DISABLE TRIGGER set_updated_at;
ALTER TABLE users ENABLE TRIGGER set_updated_at;
🔹Удалить триггер:
DROP TRIGGER set_updated_at ON users;
🔹Если несколько триггеров одного типа — они срабатывают по алфавиту имён.
Давайте им понятные префиксы (t10_…, t20_…).
Где новички чаще всего ошибаются ⚠️
1️⃣ «Скрытая магия»: непонятно, что меняет данные.
Решение — документируйте триггеры и давайте им говорящие имена.
2️⃣ Массовые операции: FOR EACH ROW на миллионах строк может замедлить UPDATE. Если возможно — переносите часть логики в периодические задачи или используйте FOR EACH STATEMENT.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤6👍5👌4🗿2👏1
мы постоянно улучшаем наш сервис и нам важно ваше мнение 🙌
заполните, пожалуйста, короткую форму — это займет пару минут:
https://docs.google.com/forms/d/e/1FAIpQLSd5kdm4NfgquCKWptO83R9qmyuIZAyk1fSzK4v3fiTIp7D84w/viewform
🎁 бонус: премиум на нашей платформе получат 2 автора самых интересных предложений.
📌 в поле «ваши контактные данные» укажите ваш @username в Telegram.
🗓 сбор обратной связи — до 27 числа.
спасибо!💛
заполните, пожалуйста, короткую форму — это займет пару минут:
https://docs.google.com/forms/d/e/1FAIpQLSd5kdm4NfgquCKWptO83R9qmyuIZAyk1fSzK4v3fiTIp7D84w/viewform
спасибо!
Please open Telegram to view this post
VIEW IN TELEGRAM
Google Docs
Форма обратной связи SQL Academy
Мы постоянно пытаемся сделать наш сервис лучше, а для этого нам важно ваше мнение!
❤13🔥7👍1
Blob в mysql или ссылки на файлы — как выбрать? 🗂️
Задача: нужно хранить файлы (фото, pdf, видео). Где их держать: прямо в базе (BLOB) или во внешнем хранилище (например, S3) и в БД — только ссылку? Разберёмся коротко и понятно.
Что такое blob и «ссылки»
🔹 BLOB — двоичные данные прямо в таблице MySQL (поле BLOB/LONGBLOB).
🔹 Ссылка — файл лежит во внешнем хранилище, а в БД мы храним URL + метаданные (имя, размер, тип).
Когда хранить в базе (blob) 📦
Подходит, если:
🔹файлы небольшие (аватарки, превью, ≤ ~1 МБ);
🔹важна атомарность: данные и файл сохраняются/откатываются вместе;
🔹проект простой, без CDN и стриминга.
Плюсы: просто, транзакционно, один бэкап.
Минусы: база быстро растёт, бэкапы тяжелее, отдавать большие файлы медленно.
Мини-пример
Когда хранить снаружи (ссылки) 🔗
Подходит, если:
🔹файлов много или они крупные (фото/видео/доки);
🔹нужна раздача через CDN (быстрая доставка);
🔹важны дешёвое хранилище и лёгкие бэкапы БД.
Плюсы: масштабируемо, дёшево, быстро отдаётся.
Минусы: две системы (БД + хранилище).
Мини-пример
Быстрый чек-лист выбора ✅
🔹Размер: маленькие → BLOB; большие → ссылка.
🔹Транзакционность (вместе с бизнес-данными): нужна → BLOB.
🔹 Отдача файлов пользователям: нужен CDN → ссылка.
🔹Бэкапы и восстановление: хочется лёгких дампов → ссылка.
🔹Стоимость хранения: экономим → ссылка.
Вывод
🔹BLOB хорош для маленьких файлов и строгой консистентности.
🔹Ссылки — почти всегда лучший выбор для больших объёмов, скорости и экономии.
Задача: нужно хранить файлы (фото, pdf, видео). Где их держать: прямо в базе (BLOB) или во внешнем хранилище (например, S3) и в БД — только ссылку? Разберёмся коротко и понятно.
Что такое blob и «ссылки»
🔹 BLOB — двоичные данные прямо в таблице MySQL (поле BLOB/LONGBLOB).
🔹 Ссылка — файл лежит во внешнем хранилище, а в БД мы храним URL + метаданные (имя, размер, тип).
Когда хранить в базе (blob) 📦
Подходит, если:
🔹файлы небольшие (аватарки, превью, ≤ ~1 МБ);
🔹важна атомарность: данные и файл сохраняются/откатываются вместе;
🔹проект простой, без CDN и стриминга.
Плюсы: просто, транзакционно, один бэкап.
Минусы: база быстро растёт, бэкапы тяжелее, отдавать большие файлы медленно.
Мини-пример
CREATE TABLE file_blobs (
id BIGINT PRIMARY KEY,
name VARCHAR(255),
mime VARCHAR(100),
size INT,
-- для дедупликации
sha256 BINARY(32),
-- сам файл
data LONGBLOB NOT NULL,
created_at TIMESTAMP,
UNIQUE KEY (sha256)
);
Когда хранить снаружи (ссылки) 🔗
Подходит, если:
🔹файлов много или они крупные (фото/видео/доки);
🔹нужна раздача через CDN (быстрая доставка);
🔹важны дешёвое хранилище и лёгкие бэкапы БД.
Плюсы: масштабируемо, дёшево, быстро отдаётся.
Минусы: две системы (БД + хранилище).
Мини-пример
CREATE TABLE files (
id BIGINT PRIMARY KEY,
name VARCHAR(255),
mime VARCHAR(100),
size INT,
sha256 BINARY(32),
-- https://... или s3://...
storage_url VARCHAR(2048) NOT NULL,
created_at TIMESTAMP,
UNIQUE KEY (sha256)
);
Быстрый чек-лист выбора ✅
🔹Размер: маленькие → BLOB; большие → ссылка.
🔹Транзакционность (вместе с бизнес-данными): нужна → BLOB.
🔹 Отдача файлов пользователям: нужен CDN → ссылка.
🔹Бэкапы и восстановление: хочется лёгких дампов → ссылка.
🔹Стоимость хранения: экономим → ссылка.
Вывод
🔹BLOB хорош для маленьких файлов и строгой консистентности.
🔹Ссылки — почти всегда лучший выбор для больших объёмов, скорости и экономии.
❤16👍6🔥4
SQL-Academy-Interview-Questions-ru.pdf
1.2 MB
Топ-вопросы с собеседований по SQL + ответы 📝
Мы собрали самые популярные вопросы и варианты ответов — читайте по ссылке:
https://sql-academy.org/ru/interview-questions
Чтобы было удобнее, подготовили офлайн-версию (PDF). Сохраните и используйте, чтобы быстро освежить знания перед важным собесом.
📥 офлайн-версия — в файле к этому посту
удачи на собеседованиях! 💪
Мы собрали самые популярные вопросы и варианты ответов — читайте по ссылке:
https://sql-academy.org/ru/interview-questions
Чтобы было удобнее, подготовили офлайн-версию (PDF). Сохраните и используйте, чтобы быстро освежить знания перед важным собесом.
📥 офлайн-версия — в файле к этому посту
удачи на собеседованиях! 💪
🔥44👍15❤7😎5🙏2😢1
Мини-квиз по дате и времени в PostgreSQL
1️⃣ Вопрос 1: Парсинг даты одной функцией
a) 16/08/2024
b) 2024-16-08
c) 2024-08-16
d) Ошибка парсинга
Правильный ответ:c) 2024-08-16
2️⃣ Вопрос 2: Разница в днях
a) 13
b) 14
c) 15
d) 16
Правильный ответ:b) 14
3️⃣ Вопрос 3: Номер недели (ISO) для актуальной даты
a) 0
b) 1
c) 52
d) 53
Правильный ответ:b) 1
4️⃣ Вопрос 4: Переход через полночь
a) 2024-08-16 25:00:00
b) 2024-08-17 00:00:00
c) 2024-08-17 01:00:00
d) 2024-08-16 23:02:00
Правильный ответ:c) 2024-08-17 01:00:00
1️⃣ Вопрос 1: Парсинг даты одной функцией
SELECT to_date('16-08-2024', 'DD-MM-YYYY');
a) 16/08/2024
b) 2024-16-08
c) 2024-08-16
d) Ошибка парсинга
Правильный ответ:
2️⃣ Вопрос 2: Разница в днях
SELECT DATE '2024-03-15' - DATE '2024-03-01';
a) 13
b) 14
c) 15
d) 16
Правильный ответ:
3️⃣ Вопрос 3: Номер недели (ISO) для актуальной даты
SELECT EXTRACT(WEEK FROM DATE '2026-01-01');
a) 0
b) 1
c) 52
d) 53
Правильный ответ:
4️⃣ Вопрос 4: Переход через полночь
SELECT TIMESTAMP '2024-08-16 23:00:00' + INTERVAL '2 hours';
a) 2024-08-16 25:00:00
b) 2024-08-17 00:00:00
c) 2024-08-17 01:00:00
d) 2024-08-16 23:02:00
Правильный ответ:
🔥32❤12👍9👨💻7
Всем привет! На канале Data analysis | Анализ данных | DA разбираются темы и вопросы, которые должен знать аналитик данных, имеющий опыт 3-6 лет. Все темы взяты из реальных вакансий, опубликованных на hh.ru.
Будет полезно, если вы являетесь аналитиком данных (начинающим или опытным) или работаете по смежной профессии, либо просто интересуетесь базами данных, Python, SQL, экономикой и финансами и всеми производными от этих тем.
Список разобранных вопросов:
🐍 Python:
📖 SQL:
📖 Базы данных:
⚙️ Инструменты:
🐞 А/Б тестирование:
📊 Работа с данными:
В ближайшем будущем будем разбирать👇
— Больше про SQL и базы данных: архитектуру и т.п.
— Больше питоновских библиотек и кейсов
— Про банковские данные
— Актуальные инструменты, в частности BI-инструменты и ETL-инструменты
Будет полезно, если вы являетесь аналитиком данных (начинающим или опытным) или работаете по смежной профессии, либо просто интересуетесь базами данных, Python, SQL, экономикой и финансами и всеми производными от этих тем.
Список разобранных вопросов:
— Эмбеддинги предложений
— Алгоритм кластеризации
— Кластеризация текстовой информации
— Визуализация: Matplotlib
— Визуализация: Seaborn
— Python в Tableau
— Python + SQL: Cx_oracle
— Большие данные в Python: Dask
— Массовая загрузка файлов в БД
— Продвинутая запись в Excel: XlsxWriter
— Аномалии в данных
— Аномалии в данных: применение скользящих средних
— Автоматизация подбора чисел
— Анализ динамики
— PARTITION (оконные функции)
— PARTITION (партиционирование)
— Процедуры: разбор IN | OUT | IN OUT
— Процедуры: объявления и исключения
— PACKAGE (пакеты)
— Циклы LOOP, WHILE, FOR
— CURSOR
— Индексы
— Представления (Views)
— Материализованные и нематериализованные views
— Hints (хинты)
— EXPLAIN PLAN
— TRIGGER (триггеры)
— Какие бывают базы данных
— Виды БД наглядно
— ACID и BASE
— OLAP-кубы
— Проектирование баз данных
— Разница между БД и DWH
— Витрины данных
— ETL и ELT процессы
— Звездочка, снежинка, Data Vault
— Слои данных в DWH
— Нормализация
⚙️ Инструменты:
— Обзор Hadoop
— Обзор Hive
— Обзор Impala
— Обзор Airflow
— Обзор ClickHouse
— Tableau
— Arenadata Catalog
— Qlik Sense
— Informatica PowerCenter
🐞 А/Б тестирование:
— Основы А/Б тестов
— А/Б тесты на практике
— Математические методы проверки результатов
— Инструменты А/Б тестирования
📊 Работа с данными:
— Парадокс Симпсона
— Банковские клиенты
— Клиентская информация в банковском DWH
— Банковские продукты
— Продуктовая информация в банковском DWH
— Счета, баланс и фин рез в банковском DWH
— Качество данных
— Метаданные
— Source-to-Target Mapping
В ближайшем будущем будем разбирать
— Больше про SQL и базы данных: архитектуру и т.п.
— Больше питоновских библиотек и кейсов
— Про банковские данные
— Актуальные инструменты, в частности BI-инструменты и ETL-инструменты
Please open Telegram to view this post
VIEW IN TELEGRAM
Telegram
Data analysis | Анализ данных | DA
Про анализ данных (Data analysis): базы данных (БД), SQL, Python, IT и многое другое, полезное аналитикам и не только
По рекламе и остальным вопросам - @connection_07
Реклама на бирже - https://telega.in/channels/business_stats/card
По рекламе и остальным вопросам - @connection_07
Реклама на бирже - https://telega.in/channels/business_stats/card
🔥8❤5👍2
Soft Delete, Hard Delete или Архив? Как правильно удалять данные 🗑️
Задача: Пользователь нажал «Удалить аккаунт». Что делать базе? Стереть навсегда? Скрыть? Или перенести в чулан? Разбираем три стратегии.
1️⃣ Hard Delete (Физическое удаление) 🧨
Классический DELETE. Данные исчезают, место освобождается.
Плюсы:
🔹 Максимальная скорость работы базы (таблицы компактные).
🔹 Соблюдение GDPR (право на забвение).
🔹 Нет проблем с уникальностью (email можно использовать повторно сразу).
Минусы: Данные не восстановить без бэкапа. Опасность «битых ссылок», если забыли настроить каскадное удаление (Foreign Keys).
2️⃣ Soft Delete (Мягкое удаление) 👻
Мы не удаляем строку, а ставим метку deleted_at = NOW(). Данные лежат на месте, но приложение делает вид, что их нет.
Плюсы:
🔹 Легко восстановить («Ой, я случайно!»).
🔹 Сохраняется история и связи.
Минусы:
🔸 Раздувание таблицы: База хранит тонны «мертвых» данных, индексы тормозят.
🔸 Сложность запросов: Везде нужно писать WHERE deleted_at IS NULL.
🔸 Проблема уникальности: Если bob@site.com удален «мягко», создать нового Боба с тем же email не даст уникальный индекс (нужен частичный индекс).
3️⃣ Archiving (Архивирование / Cold Storage) 📦
Гибридный подход. Данные удаляются из основной («горячей») таблицы, но перед этим переносятся в отдельную таблицу-архив (users_archive).
Как это работает:
🔹Стартуем транзакцию.
🔹INSERT данные в таблицу архива.
🔹DELETE данные из основной таблицы.
🔹Коммит.
Плюсы:
✅ Основная таблица летает (в ней только активные данные).
✅ История сохранена (в архиве).
✅ Нет проблем с уникальными индексами в основной таблице.
Элегантный перенос одной командой (PostgreSQL) :
Задача: Пользователь нажал «Удалить аккаунт». Что делать базе? Стереть навсегда? Скрыть? Или перенести в чулан? Разбираем три стратегии.
1️⃣ Hard Delete (Физическое удаление) 🧨
Классический DELETE. Данные исчезают, место освобождается.
Плюсы:
🔹 Максимальная скорость работы базы (таблицы компактные).
🔹 Соблюдение GDPR (право на забвение).
🔹 Нет проблем с уникальностью (email можно использовать повторно сразу).
Минусы: Данные не восстановить без бэкапа. Опасность «битых ссылок», если забыли настроить каскадное удаление (Foreign Keys).
2️⃣ Soft Delete (Мягкое удаление) 👻
Мы не удаляем строку, а ставим метку deleted_at = NOW(). Данные лежат на месте, но приложение делает вид, что их нет.
Плюсы:
🔹 Легко восстановить («Ой, я случайно!»).
🔹 Сохраняется история и связи.
Минусы:
🔸 Раздувание таблицы: База хранит тонны «мертвых» данных, индексы тормозят.
🔸 Сложность запросов: Везде нужно писать WHERE deleted_at IS NULL.
🔸 Проблема уникальности: Если bob@site.com удален «мягко», создать нового Боба с тем же email не даст уникальный индекс (нужен частичный индекс).
3️⃣ Archiving (Архивирование / Cold Storage) 📦
Гибридный подход. Данные удаляются из основной («горячей») таблицы, но перед этим переносятся в отдельную таблицу-архив (users_archive).
Как это работает:
🔹Стартуем транзакцию.
🔹INSERT данные в таблицу архива.
🔹DELETE данные из основной таблицы.
🔹Коммит.
Плюсы:
✅ Основная таблица летает (в ней только активные данные).
✅ История сохранена (в архиве).
✅ Нет проблем с уникальными индексами в основной таблице.
Элегантный перенос одной командой (PostgreSQL) :
WITH moved_rows AS (
DELETE FROM users
WHERE id = 101
RETURNING *
)
INSERT INTO users_archive
SELECT * FROM moved_rows;
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥28👍9❤4👎1👌1🆒1