Горячее
Лучшее
Свежее
Подписки
Сообщества
Блоги
Эксперты
Войти
Забыли пароль?
или продолжите с
Создать аккаунт
Регистрируясь, я даю согласие на обработку данных и условия почтовых рассылок.
или
Восстановление пароля
Восстановление пароля
Получить код в Telegram
Войти с Яндекс ID Войти через VK ID
ПромокодыРаботаКурсыРекламаИгрыПополнение Steam
Пикабу Игры +1000 бесплатных онлайн игр Погрузись в «Свидания с отличиями» — увлекательную романтическую игру в жанре «найди отличия», где ты знакомишься с обаятельными девушками, узнаешь их истории и организуешь незабываемые свидания. Тебя ждут десятки уровней, полных эмоций, и множество очаровательных спутниц!

Свидания с отличиями

Казуальные, Головоломки, Новеллы

Играть

Топ прошлой недели

  • solenakrivetka solenakrivetka 7 постов
  • Animalrescueed Animalrescueed 53 поста
  • ia.panorama ia.panorama 12 постов
Посмотреть весь топ

Лучшие посты недели

Рассылка Пикабу: отправляем самые рейтинговые материалы за 7 дней 🔥

Нажимая «Подписаться», я даю согласие на обработку данных и условия почтовых рассылок.

Спасибо, что подписались!
Пожалуйста, проверьте почту 😊

Помощь Кодекс Пикабу Команда Пикабу Моб. приложение
Правила соцсети О рекомендациях О компании
Промокоды Биг Гик Промокоды Lamoda Промокоды МВидео Промокоды Яндекс Маркет Промокоды Пятерочка Промокоды Aroma Butik Промокоды Яндекс Путешествия Промокоды Яндекс Еда Постила Футбол сегодня
0 просмотренных постов скрыто
4
VelStyling
VelStyling
Серия SQL: знакомство

GROUP BY - группировка или источник факапов⁠⁠

2 месяца назад

Все знают GROUP BY.
Тот самый оператор, который превращает кучу строк в аккуратную табличку с суммами и средними.

Но можно и по-другому взглянуть на GROUP BY

А пока подписывайся на мой канал На связи: SQL Там я публикую посты про особенности и нюансы SQL. Этот канал про то, как не бояться баз данных, понимать, что такое JOIN, GROUP BY и почему NULL ≠ 0. Его я веду с нуля подписчиков. Присоединяйся!

GROUP BY - группировка или источник факапов

В большинстве случаев GROUP BY используют вместе с агрегирующими функциями SUM, COUNT или AVG.

Но есть и другие возможности использования группировки.

  1. В качестве изящной замены DISTINCT

    SELECT department FROM employees GROUP BY department;

    работает так же, как

    SELECT DISTINCT department FROM employees;

  2. Группировать можно по выражениям, а не только по столбцам

    Например, хочешь посчитать заказы по годам:

    SELECT EXTRACT(YEAR FROM created_at) AS year, COUNT(*)

    FROM orders

    GROUP BY EXTRACT(YEAR FROM created_at);

    Или сгруппировать товары по тысячам рублей:

    SELECT (price / 1000)::int AS price_group, COUNT(*)

    FROM products

    GROUP BY (price / 1000)::int;

  3. GROUP BY умеет строить иерархии

    ROLLUP, CUBE, GROUPING SETS — три команды богов:

    SELECT region, city, SUM(sales)

    FROM orders

    GROUP BY ROLLUP (region, city);

    → покажет суммы по городам, по регионам и общий итог.
    И всё это одним запросом.

  4. NULL — это тоже группа

    Если у тебя несколько строк с NULL в поле department,
    то GROUP BY department соберёт их все в одну группу NULL.

    SELECT department, COUNT(*)

    FROM employees

    GROUP BY department;

    Логичней использовать COALESCE, чтобы потом не работать с пустыми строками

    SELECT COALESCE(department, 'Unknown') AS department, COUNT(*)

    FROM employees

    GROUP BY COALESCE(department, 'Unknown');

  5. SELECT vs GROUP BY — всё, что не агрегат, должно быть в GROUP BY

    SELECT department, name, COUNT(*)

    FROM employees

    GROUP BY department;

    Запрос упадёт, потому что name не в агрегате и не в GROUP BY.

    В PostgreSQL есть хитрости: можно использовать array_agg(name) или string_agg(name, ', ')

  6. GROUP BY и оконные функции — не конкуренты

    GROUP BY сжимает таблицу.
    OVER(PARTITION BY) — сохраняет строки, но добавляет агрегат.

    SELECT name, department,

    SUM(salary) OVER (PARTITION BY department) AS dep_total

    FROM employees;

  7. SQL сам решает, как группировать

    PostgreSQL может выбрать:

    • HashAggregate — если данных много

    • Sort + GroupAggregate — если их мало или мало уникальных значений

    То есть одна и та же команда GROUP BY под капотом работает по-разному.
    Вот почему один и тот же запрос на 10k строк работает мгновенно, а на 10M — вечность.

    PostgreSQL не просто тупо группирует строки, а выбирает стратегию (план выполнения) — как именно эту группировку реализовать.

    Это можно отследить в EXPLAIN и уже потом контролировать включением/выключением конкретных алгоритмов.

    SET enable_hashagg = off;

    SET enable_sort = off;

    Это полезно для тестирования или отладки - посмотреть, как изменится план.

GROUP BY — это не просто «посчитать среднюю зарплату по отделу».
Это мощный инструмент, который может:

  • имитировать DISTINCT

  • строить иерархические отчёты

  • объединяться с оконными функциями

  • …и при этом легко устроить тебе день боли, если ты не знаешь, что делаешь 😅

Показать полностью 1
[моё] SQL Аналитик Аналитика Анализ данных База данных Саморазвитие Запросы Длиннопост
0
prokhorenkonn
prokhorenkonn

Как правильно заложить маркетинговый бюджет: практичные методы и здравый расчёт⁠⁠

2 месяца назад

Сколько выделять на продвижение — вопрос, который вызывает споры у каждого бизнеса. Кто-то действует по принципу «сколько останется», другие считают через себестоимость продукта. На деле разумнее опираться на несколько проверенных подходов.

Метод «доля от выручки»

Один из самых популярных способов — выделять процент от текущих доходов.

  • Для молодых компаний и стартапов ради быстрого роста — 20–30%.

  • В отраслях с высокой конкуренцией — до 40%.

  • В среднем бизнес направляет 5–20% в зависимости от масштаба и узнаваемости бренда.

Плюсы: легко считать и объяснить.
Минусы: не всегда есть связь с конкретными задачами, можно тратить, но не получать результата.

Ориентация на прошлый опыт

Если продвижение уже велось, используйте аналитику. Сравните кампании, оставьте только работающие каналы, а неэффективные урежьте. Это позволяет увеличивать отдачу без наращивания общего бюджета.

Бюджет от целей и задач

Сумма должна определяться приоритетами. Нужно раскрутить конкретный продукт? Сфокусируйтесь на нём. Продвигаете бренд в целом? Ищите форматы для широкой аудитории. Всё зависит от понимания целевой аудитории и ваших конкурентных преимуществ.

UNIT-экономика и отчётность

Альтернативный путь — считать от финансовых показателей. Смотрите:

  • сколько денег ушло на рекламу,

  • как выросла прибыль,

  • сколько стоит продвижение одной единицы товара,

  • какая остаётся маржа.

Такой подход позволяет оперативно корректировать расходы и держать баланс между затратами и прибылью.

Сравнение с рынком

По данным исследований:

  • малый бизнес тратит в среднем около 20% оборота на маркетинг,

  • средний — примерно 10,5%,

  • крупный — около 9%.

Это полезный ориентир, чтобы понять, не завышаете ли вы долю вложений.

Главное

Идеальной универсальной формулы нет. На разных стадиях развития компании работают разные методы: процент от выручки, анализ прошлых кампаний, расчёт через цели или UNIT-экономику. Лучший вариант — комбинировать подходы и регулярно проверять эффективность расходов. Тогда бюджет станет инструментом роста, а не «строчкой для отчёта».

Показать полностью
[моё] Аналитика Финансовая грамотность Финансы Бизнес Предпринимательство Малый бизнес Развитие Маркетинг Бизнес по-русски Стартап Бизнес-идея Боги маркетинга Интернет-маркетинг Услуги Маркетологи Продажа Анализ Аналитик Текст
1
3
VelStyling
VelStyling
Серия SQL: знакомство

Псевдонимы в SQL⁠⁠

2 месяца назад

Псевдонимы в SQL (алиасы) кажутся «косметикой», но у них есть подводные камни и тонкости, которые реально влияют на запросы.

Псевдонимы - это временные имена для таблиц или столбцов внутри запроса.

Псевдонимы в SQL

В моем канале На связи: SQL уже есть про это посты: вот этот. Канал я веду с нуля подписчиков. Чтобы показать, что аналитика и SQL это не страшно, а интересно. Присоединяйся, если ты тоже хочешь начать изучать SQL или вспомнить и осознать некоторые нюансы.

SELECT c.name AS customer_name

FROM customers c;

  • c — алиас таблицы customers

  • customer_name — алиас для колонки c.name

Внутри результата ты видишь только customer_name.

Где применяются

Сокращение длинных имён

SELECT o.id, c.name

FROM orders o

JOIN customers c ON o.customer_id = c.id;

- читабельнее, чем всё время писать orders.id, customers.name

JOIN и self-join
Без алиасов нельзя отличить таблицы при самосоединении:

SELECT e1.name, e2.name
FROM employees e1
JOIN employees e2 ON e1.manager_id = e2.id;

Агрегация и подзапросы
Алиас часто обязателен:

SELECT avg(salary) AS avg_salary

FROM employees;

Derived tables (подзапросы в FROM)
Тут алиас обязателен:

SELECT sub.department, sub.cnt

FROM ( SELECT department, count(*) cnt

FROM employees

GROUP BY department

) sub;

Где их нельзя применять / ограничения

В том же уровне WHERE

SELECT salary * 1.2 AS new_salary

FROM employees

WHERE new_salary > 5000; -- ❌ Ошибка

  • Алиасы доступны только в SELECT/ORDER BY, но не в WHERE или GROUP BY.
    → нужно повторно писать выражение или завернуть в CTE.

    Порядок обработки
    SQL выполняется в порядке: FROM → JOIN → WHERE → GROUP BY → HAVING → SELECT → ORDER BY → LIMIT.
    Алиасы появляются только после SELECT.
    Поэтому:

    • в WHERE и GROUP BY алиасы ещё не видны;

    • в ORDER BY алиасы уже можно использоват

Нюансы, которые часто забывают

  1. Алиасы влияют только на внешний уровень запроса
    Они не меняют структуру таблицы.
    В EXPLAIN ты увидишь исходные имена столбцов, а не алиасы.

  2. В подзапросах алиас обязателен для таблицы
    Даже если кажется, что можно без него.

SELECT *

FROM (SELECT 1) -- ❌ Ошибка

SELECT *

FROM (SELECT 1) AS t;

  1. ORDER BY может использовать алиас
    Ускоряет жизнь:

    SELECT salary * 1.2 AS new_salary
    FROM employees
    ORDER BY new_salary DESC;

  2. CTE против алиасов
    Если выражение слишком длинное (например, CASE WHEN …), лучше вынести его в CTE вместо алиаса в SELECT → так его можно переиспользовать и в WHERE, и в ORDER BY.

  3. Алиасы могут влиять на читаемость, но и запутывать
    Пример анти-паттерна:

    SELECT u.id AS order_id -- ❌ псевдоним вводит в заблуждение
    FROM users u;

    → плохая идея, потому что вводит читателя в ошибку.

Итог: алиасы — не просто косметика. Это инструмент:

  • для читаемости;

  • для самосоединений и подзапросов;

  • для управления порядком сортировки.

Но они не живут дольше SELECT-а

Подписывайся на мой канал На связи SQL и давай изучать особенности вместе!

Показать полностью 1
[моё] Анализ Аналитика Анализ данных Аналитик SQL Microsoft Excel База данных Запросы Саморазвитие Длиннопост
0
4
VelStyling
VelStyling
Серия SQL: знакомство

Неочевидные факты про JOIN⁠⁠

2 месяца назад

Про JOIN обычно пишут общую теоретическую информацию. Всегда упоминают виды JOIN-ов: INNER, LEFT, RIGHT, FULL, CROSS, а за кулисами могут остаться интересные факты, подводные камни и тонкости, которые редко упоминаются, но которые могут реально пригодиться.

Неочевидные факты про JOIN

В моем канале На связи: SQL уже есть про это посты: вот этот и вот этот. Канал я веду с нуля подписчиков. Чтобы показать, что аналитика и SQL это не страшно, а интересно. Присоединяйся, если ты тоже хочешь начать изучать SQL или вспомнить и осознать некоторые нюансы.

Неочевидные факты про JOIN

Условие в ON vs WHERE

  • Для INNER JOIN — разницы нет, фильтрация в ON или в WHERE даст одинаковый результат.

  • Но для LEFT JOIN это уже не так:

    • ON фильтрует при объединении (строка может остаться с NULL в правой таблице).

    • WHERE фильтрует после — и может "выбросить" строки, ради которых делался LEFT JOIN.

👉 Классический баг у новичков: пишут условие в WHERE и не понимают, почему LEFT превратился в INNER.

Предположим, у нас есть две таблицы:

orders (таблица заказов):

order_id | customer_id | amount

---------|-------------|--------

1 | 1 | 100

2 | 2 | 200

3 | 1 | 150

customers (таблица клиентов):

customer_id | country

------------|---------

1 | USA

2 | UK

3 | USA

И есть два запроса:

SELECT o.order_id, c.customer_id, c.country

FROM orders o

LEFT JOIN customers c ON o.customer_id = c.customer_id

AND c.country = 'USA';

SELECT o.order_id, c.customer_id, c.country

FROM orders o

LEFT JOIN customers c ON o.customer_id = c.customer_id

WHERE c.country = 'USA';

Результаты этих запросов будут одинаковы?

Можно писать свои рассуждения в комментариях.

JOIN на неравенстве

Обычно мы пишем ON a.id = b.id, но можно и:

SELECT *

FROM a

JOIN b ON a.value BETWEEN b.min AND b.max;

Это называется non-equi join (неравенственный джойн).
👉 В BI и аналитике это часто используют для «поиска диапазона» (например, попадает ли дата заказа в акцию).
Но! Такой JOIN почти всегда тяжелее, потому что индексы плохо помогают.

FULL JOIN в проде почти не используют

Многие базы его поддерживают, но реально на проектах встречается редко. Почему?

  • Почти всегда можно заменить комбинацией LEFT JOIN UNION RIGHT JOIN.

  • А оптимизаторы некоторых СУБД работают с FULL OUTER JOIN медленнее.
    👉 Часто факт наличия FULL JOIN в запросе сигнализирует, что "что-то не так со схемой данных".

CROSS JOIN — не только для Декарта

Все думают, что CROSS JOIN = "перемножить всё на всё". Но он используется:

  • для генерации тестовых данных:

SELECT d::date

FROM generate_series('2025-01-01', '2025-01-31', interval '1 day') d

CROSS JOIN users;

для построения матриц, календарей, отчетов с дырками.
👉 То есть CROSS JOIN часто — инструмент BI-разработчика

JOIN и NULL — подстава

  • NULL = NULL → всегда FALSE.
    Поэтому если соединяешь таблицы по колонке с NULL, то такие строки просто теряются.
    👉 В проде это часто ломает аналитику: ожидали, что будет связь «пустое с пустым», а SQL этого не понимает.

Производительность JOIN-ов

  • Много JOIN-ов (10+) ≠ всегда медленно. Оптимизаторы умеют работать с огромными планами.

  • Но JOIN + функции (ON lower(a.name) = lower(b.name)) почти всегда убивает индекс → дорого.
    👉 Лучшее решение — хранить данные в нормализованном виде (например, имена в нижнем регистре).

ANTI JOIN

Вместо NOT IN или NOT EXISTS можно писать LEFT JOIN ... WHERE b.id IS NULL.
Это часто быстрее, особенно в старых версиях MySQL.
👉 Но не забывай: NOT IN (NULL, ...) ведет себя неожиданно (возвращает пустой набор).

JOIN ≠ JOIN ORDER

SQL — декларативный язык. Ты пишешь JOIN-ы в любом порядке, но оптимизатор сам решает, какую таблицу читать первой, как переставить местами соединения. Поэтому писать «самую маленькую таблицу первой» часто не имеет смысла. Но иногда хинты (JOIN ORDER, FORCE JOIN, USE INDEX) всё же нужны, когда оптимизатор ошибается.

Когда мы пишем:

SELECT *

FROM orders o

JOIN customers c ON o.customer_id = c.id

JOIN regions r ON c.region_id = r.id;

мы как бы говорим:
👉 «Дай мне все заказы, вместе с клиентами и регионами».

НО! Мы не указываем порядок, в котором эти таблицы реально будут соединяться.
Оптимизатор (query planner) сам решает:

  • какую таблицу читать первой;

  • по какому индексу идти;

  • в каком порядке выполнять JOIN-ы.

И этот порядок почти всегда ≠ порядок в SQL-запросе.

Как это работает на практике

  • Оптимизатор строит граф зависимостей между таблицами и условиями.

  • Считает «стоимость» разных стратегий (в PostgreSQL это cost-based optimizer).

  • Выбирает план с минимальной стоимостью: например, начать с маленькой таблицы, потом по индексу сходить в большую.

OIN ORDER hints

Иногда оптимизатор ошибается. Причины:

  • Неправильная статистика (например, таблица только что обновилась).

  • Очень сложный запрос (10+ JOIN-ов, подзапросы).

  • Особенности движка (MySQL раньше любил «сначала левую таблицу»).

Тогда СУБД позволяют подсказать оптимизатору:

  • FORCE ORDER (SQL Server, Oracle) → использовать JOIN-ы в том порядке, как написаны.

  • LEADING (Oracle) → указать, с какой таблицы начать.

  • USE INDEX (MySQL) → подсказать, какой индекс использовать.

  • PostgreSQL не имеет FORCE JOIN, но можно:

    • отключить конкретные алгоритмы (SET enable_hashjoin = off;)

    • использовать LATERAL, JOIN LATERAL, CROSS JOIN чтобы «подсказать» порядок.


🔹 Когда порядок JOIN реально важен

  1. Суперсложные запросы (20+ таблиц).
    Оптимизатор может выбрать очень дорогой план → запрос работает минуты/часы.
    Иногда правильный хинт → ускорение в десятки раз.

  2. Необновлённая статистика.
    Оптимизатор думает: «таблица маленькая», но на самом деле она разрослась. → выбирает плохой порядок JOIN.

  3. LIMIT + ORDER BY.
    Тут реально важно, с чего начать — иногда оптимизатор «тянет» всю таблицу, хотя мог бы остановиться раньше.


🔹 Лайфхак для практики

  • В PostgreSQL можно посмотреть план:

    EXPLAIN (ANALYZE, BUFFERS) SELECT ...

    → увидишь реальный JOIN order.

  • Не доверяй слепо «писать маленькую таблицу первой» — это миф, из старых времён MySQL.

  • Иногда лучше переписать запрос так, чтобы оптимизатору нечего было гадать. Например, вынести фильтрацию в CTE или subquery.

JOIN — это не только "соединить таблицы", а целый набор особенностей: от NULL и порядка фильтрации до генерации календарей через CROSS JOIN.

Подписывайся на мой канал На связи SQL и давай изучать особенности вместе!

Показать полностью 1
[моё] SQL Join Анализ Аналитик Аналитика Анализ данных Microsoft Excel База данных Саморазвитие Длиннопост
0
3
VelStyling
VelStyling
Серия SQL: знакомство

NULL, Но(у)ль, Неизвестно, Пусто... Что это все такое⁠⁠

2 месяца назад

NULL — это специальное значение в SQL, которое означает отсутствие данных или неизвестное значение. Важно понимать, что NULL ≠ 0 и NULL ≠ пустая строка (‘’).

А пока подписывайся на мой канал На связи: SQL Там я публикую посты про особенности и нюансы SQL. Этот канал про то, как не бояться баз данных, понимать, что такое JOIN, GROUP BY и почему NULL ≠ 0. Его я веду с нуля подписчиков. И пост про NULL уже ждет тебя! Присоединяйся!

NULL, Но(у)ль, Неизвестно, Пусто... Что это все такое

NULL не равен ничему, даже самому себе. Не является числом, строкой или другим типом данных.

И это надо запомнить при работе с данными.

Все что вы будете сравнивать с NULL будет возвращаться как UNKNOWN.

Для работы с NULL есть специальные операторы.

-- Проверка на NULL

SELECT *

FROM table

WHERE column IS NULL;

-- Проверка на НЕ NULL

SELECT *

FROM table

WHERE column IS NOT NULL;

-- Замена NULL на значение

SELECT COALESCE(column, 'значение_по_умолчанию')

FROM table;

NULL появляется там, где есть необязательные поля для заполнения, при отсутствии связей между сущностями, при ошибках ввода, когда данные неизвесты.

Вообще, понятие NULL появилось в начале 1970-х годов. Разработчики реляционных БД специально создали такое значение для обозначения отсутствия данных. Это было революционным решением, позволившим хранить информацию более гибко.

Математические фокусы с NULL:

  • Любое число + NULL = NULL

  • NULL * 100 = NULL

  • NULL / 2 = NULL

  • Индексы могут работать медленнее при наличии NULL

  • Некоторые типы индексов вообще не поддерживают NULL

  • Агрегатные функции игнорируют NULL по умолчанию

Ну и коротко про то что такое Но(у)ль:
Ноль — это чётко определённое значение:

  • Числовое значение

  • Имеет математический смысл

  • Участвует в вычислениях

  • Равно самому себе

А теперь про пусто:
Пустота — отсутствие содержимого

Пустое значение может быть:

  • Пустой строкой (‘’ или “”)

  • Пустым массивом

  • Пустым объектом

  • Имеет конкретный тип данных

Рекомендации:

  • Используйте NULL для неизвестных данных

  • Применяйте 0 для числовых значений по умолчанию

  • Используйте пустые строки для незаполненных текстовых полей

Заключение

Помните: каждое из этих значений несёт свой смысл. Неправильное использование может привести к:

  • Ошибочным расчётам

  • Некорректной логике

  • Потерям данных

  • Системным ошибкам

А как вы работаете с этими значениями в своих проектах? Поделитесь опытом в комментариях!

Показать полностью 1
[моё] Null База данных Анализ данных Аналитика Аналитик SQL Microsoft Excel Большие данные Самообразование Длиннопост
1
VelStyling
VelStyling
Серия SQL: знакомство

DELETE в SQL: когда одно слово может стереть ваши данные⁠⁠

2 месяца назад

DELETE — инструменте, который может как спасти вашу базу данных от хлама, так и превратить её в пустыню за считанные секунды.

DELETE как цифровой пылесос**, который может убрать всё, что вы ему скажете. Только вот вернуть обратно будет ой как непросто!

DELETE в SQL: когда одно слово может стереть ваши данные

А пока подписывайся на мой канал На связи: SQL Там я публикую посты про особенности и нюансы SQL. Этот канал про то, как не бояться баз данных, понимать, что такое JOIN, GROUP BY и почему NULL ≠ 0. Его я веду с нуля подписчиков. Присоединяйся!

Базовый синтаксис:

DELETE FROM таблица
WHERE условие;

Можно использовать EXISTS с подзапросами

DELETE FROM orders

WHERE EXISTS (

SELECT 1

FROM customers

WHERE customers.id = orders.customer_id

AND customers.status = 'deleted' );

Удаляет заказы неактивных клиентов.

Можно использовать JOIN

DELETE o

FROM orders o

INNER JOIN customers c ON o.customer_id = c.id

WHERE c.registration_date < '2020-01-01';

Удаляет заказы клиентов, зарегистрированных до 2020 года.

Как происходит удаление записей?

Физическое удаление в SQL — это не мгновенное стирание данных с диска. Когда вы выполняете DELETE:

  • Система записывает операцию в журнал транзакций

  • Помечает удалённые строки как свободные

  • Физическое место может быть использовано для новых данных

  • Сами данные остаются в файле некоторое время

Формируется основной файл .mdf (или аналогичный). Также информация записывается в журнал транзакций. Сроки хранения удаленных данных зависят от:
- модели восстановления базы данных
- активности базы данных
- настроек резервного копирования
- объема свободного места

Удаленные данные могут храниться до следующего бэкапа или до перезаписи журнала.

Способы восстановления данных после DELETE

  1. Восстановление из резервной копии

    RESTORE DATABASE имя_базы FROM DISK = 'путь_к_бэкапу'

  2. Использование моментальных снимков (Snapshot)

    CREATE DATABASE имя_снимка

    ON (NAME = имя_файла, FILENAME = 'путь_к_файлу')

    AS SNAPSHOT OF исходная_база;

    Восстановление данных из снимка:

    INSERT INTO исходная_таблица

    SELECT * FROM снимок.dbo.таблица

  3. Восстановление через LSN (Log Sequence Number)

    Если есть журналы транзакций:

    BACKUP LOG имя_базы TO DISK = 'путь_к_журналу'

    Поиск удалённых записей:
    SELECT [Current LSN], [Transaction ID]

    FROM fn_dblog(NULL, NULL)

    WHERE Operation = 'LOP_DELETE_ROWS'

  4. Либо использовать специальные посторонние программы для восстановления БД

Чтобы предотвратить потерю данных:

  • Регулярно создавайте резервные копии

  • Используйте транзакции (BEGIN TRANSACTION / ROLLBACK)

  • Тестируйте DELETE-запросы на тестовой базе

  • Применяйте WHERE с осторожностью

  • Настройте политики резервного копирования

DELETE vs TRUNCATE

Многие думают, что TRUNCATE и DELETE — это одно и то же. На самом деле:

  • DELETE удаляет строки по одной и записывает каждую операцию в журнал транзакций

  • TRUNCATE мгновенно очищает таблицу, минуя журнал (кроме некоторых случаев)

При выполнении DELETE:

  • Блокируются только удаляемые строки

  • Другие транзакции могут читать незаблокированные данные

  • В некоторых СУБД возможна эскалация блокировок до уровня таблицы

  • Не затрагивает структуру индексов

  • Индексы остаются в прежнем состоянии

  • Это ускоряет процесс удаления

  • Не сбрасывает счётчики автоинкремента

  • Сохраняет текущее значение последовательности

  • Важно при работе с первичными ключами

  • Активируются триггеры AFTER DELETE

  • Можно отслеживать удалённые строки через виртуальную таблицу deleted

  • Триггеры могут отменить операцию удаления

Чтобы сохранить целостность данных можно использовать ON DELETE CASCADE
Это позволит там, где есть зависимость по внешним ключам произвести удаление зависимых строк.

Показать полностью 1
[моё] SQL Аналитик Аналитика Большие данные Microsoft Excel Анализ данных Эмоциональное выгорание Самообразование База данных Длиннопост
6
0
VelStyling
VelStyling
Серия SQL: знакомство

UPDATE в SQL: не путай с «обновлением Windows»⁠⁠

2 месяца назад

UPDATE — это команда, с помощью которой мы меняем данные, уже существующие в таблице.
Не добавляем новые строки (как INSERT), не удаляем (как DELETE), а правим то, что есть.

А пока подписывайся на мой канал На связи: SQL Там я публикую посты про особенности и нюансы SQL. Этот канал про то, как не бояться баз данных, понимать, что такое JOIN, GROUP BY и почему NULL ≠ 0. Его я веду с нуля подписчиков. Присоединяйся!

Базовый синтаксис выглядит следующим образом:

UPDATE table_name

SET column1 = value1,

column2 = value2

WHERE condition;

  • UPDATE table_name → в какой таблице меняем данные.

  • SET → что именно меняем и на какие значения.

  • WHERE → условие, чтобы обновить только нужные строки.

Если забыть WHERE → обновятся все строки таблицы. Классический факап новичка.

Где и когда используется?

  • Меняем телефон у клиента → UPDATE customers SET phone = '...' WHERE id = 5;

  • Уменьшаем остаток товара после покупки.

  • Обновляем статус заказа.

Проще говоря: везде, где данные живые и меняются со временем.

Можно обновлять сразу несколько строк:

UPDATE products

SET price = price * 0.9

WHERE category = 'clothes';

В этом запросе нет ограничений по количеству строк, если в таблице есть 10 строк с категорией = 'clothes', то скидка в 10% применится ко всем 10 строкам.

В UPDATE можно использовать JOIN при более сложной логике

UPDATE orders o

SET amount = amount * 1.1

FROM customers c

WHERE o.customer_id = c.id

AND c.vip = true;

Мы делаем обновления в таблице orders, но делаем их для тех покупателей, у которых есть признак ВИП. А признак ВИП хранится в таблице customers.

В этом запросе явно не указан JOIN, но с JOIN запрос выглядел бы вот так:

UPDATE orders o

SET amount = amount * 1.1

FROM orders o2

JOIN customers c ON o2.customer_id = c.id

WHERE o.id = o2.id AND c.vip = true;

Здесь больше строк, поэтому многие предпочитают первый вариант.

  • PostgreSQL, SQL Server → поддерживают UPDATE ... FROM.

  • MySQL → там другой синтаксис:

UPDATE orders o

JOIN customers c ON o.customer_id = c.id

SET o.amount = o.amount * 1.1

WHERE c.vip = true;

Т.е. в MySQL JOIN присутствует в явном виде.

RETURNING в PostgreSQL

UPDATE orders

SET status = 'done'

WHERE id = 101

RETURNING *;

Сразу получаешь обновлённые строки, без лишнего SELECT. В MySQL и SQL Server такого нет.

Deadlock при UPDATE

  • Транзакция А захватила строку 1 и ждёт строку 2.

  • Транзакция B захватила строку 2 и ждёт строку 1.

  • Обе ждут друг друга бесконечно.

База видит: «ну, так не пойдёт» → и убивает одну из транзакций, чтобы освободить дорогу.

  • При обычной блокировке ты просто ждёшь, пока другой закончит.

  • При deadlock оба ждут друг друга, и никто никогда не закончит — тупик.

В UPDATE можно использовать подзапросы:

UPDATE employees

SET salary = salary + 5000

WHERE department_id = (

SELECT id FROM departments WHERE name = 'IT'

);

Здесь UPDATE зависит от результата подзапроса.

UPDATE без SET

В некоторых СУБД (например, SQL Server) можно писать:

UPDATE table_name

SET column = column;

На вид — бесполезно. Но так можно снимать блокировки или триггерить AFTER UPDATE.

Можно использовать TOP и LIMIT при UPDATE

UPDATE TOP (10) users SET active = 0; -- для SQL Server

UPDATE users SET active = 0 LIMIT 10; -- для MySQL

А вот для PostgreSQL такого механизма нет - надо будет через CTE реализовывать.

UPDATE — мощный инструмент. Он нужен везде, где данные живут и меняются. Но:

  • всегда помни про WHERE,

  • учитывай блокировки,

  • и знай фишки СУБД (RETURNING, JOIN, LIMIT).

Напоминаю про свой канал На связи: SQL Присоединяйся для обсуждения вопросов по изучению SQL.

Показать полностью
[моё] SQL Аналитик Аналитика Системный аналитик Самообразование IT Текст Длиннопост
1
0
VelStyling
VelStyling
Серия SQL: знакомство

INSERT INTO - Простая команда с непростым характером⁠⁠

2 месяца назад

INSERT — это оператор для добавления новых строк в таблицу.

Классика выглядит так:

INSERT INTO customers (name, age, city)

VALUES ('Оля', 28, 'Москва');

Главные слова:

  • INSERT INTO — куда добавляем,

  • VALUES — что именно добавляем.

INSERT INTO - Простая команда с непростым характером

А пока подписывайся на мой канал На связи: SQL Там я публикую посты про особенности и нюансы SQL. Этот канал про то, как не бояться баз данных, понимать, что такое JOIN, GROUP BY и почему NULL ≠ 0. Его я веду с нуля подписчиков. Присоединяйся!

При вставке значений в таблицу можно выделить одиночную вставку и массовую вставку.
Одиночная - это когда в запросе содержится вставка одной строки, а массовая - нужно вставить больше чем одну строку.

INSERT INTO products (name, price) VALUES ('Яблоки', 100);

INSERT INTO products (name, price) VALUES ('Груши', 120);

-- и так 1000 раз 😅

INSERT INTO products (name, price)

VALUES

('Яблоки', 100),

('Груши', 120),

('Бананы', 150);

Один INSERT на 1000 строк работает быстрее, чем 1000 отдельных запросов, потому что база открывает и закрывает транзакцию только один раз.

Транзакция — это логическая единица работы с базой данных, набор действий (обычно INSERT, UPDATE, DELETE и т. д.), которые выполняются как одно целое.
База гарантирует, что или все действия внутри транзакции будут выполнены, или не выполнится ни одно.

Например:

  • Перевод денег с карты на карту.

    1. Снять деньги с карты А.

    2. Зачислить деньги на карту Б.

Если выполнить только первый шаг, а второй не получится — деньги «пропадут».
Транзакция гарантирует, что либо оба шага выполнятся, либо оба отменятся.

Так вот, даже если мы явно в коде не прописываем начало и окончание транзакции, то наша база автоматически оборачивает наш запрос началом и окончанием транзакции

BEGIN;
INSERT INTO products (name, price) VALUES ('Яблоки', 100);
COMMIT;

BEGIN;
INSERT INTO products (name, price) VALUES ('Груши', 120);
COMMIT;

-- и так 1000 раз 😅

BEGIN;

INSERT INTO products (name, price)

VALUES

('Яблоки', 100),

('Груши', 120),

('Бананы', 150);

COMMIT;

Но при этом вставлять одним запросом млн строк - это плохо. Можно словить блокировку. Поэтому для большого объема вставки - лучше дробить на несколько маленьких частей.

Оптимальный размер батча — подбирается экспериментально. Обычно от 5k до 50k строк за один заход.

При вставке данных в таблицу у нас часто используется уникальный идентификатор строки, часто этот идентификатор является автоинкрементом, т.е. база сама записывает значение в это поле.

CREATE TABLE users (

id SERIAL, -- автоинкремент

name TEXT

);

INSERT INTO users (name) VALUES ('Оля'); -- id = 1

INSERT INTO users (name) VALUES ('Маша'); -- id = 2

Каждый INSERT добавляет новую запись, а автоинкремент гарантирует уникальный идентификатор для этой строки.

  • Без него нужно было бы самому считать, какой следующий номер ставить.

  • Автоинкремент экономит время и предотвращает ошибки.

Но автоинкремент не гарантирует, что значения в поле id будут "последовательными", он гарантирует, что значения в этом поле будут уникальными.

Получается, что при INSERT в поле с автоинкрементом могут быть "дырки".
Это получается, например, в следующих кейсах:
1. отмененная вставка:
- Сделали INSERT, база выделила id = 5.
- Транзакцию откатили (ROLLBACK).
- Id 5 пропал, следующие вставки идут с 6.
2. Удаление строк:
- Если удалить записи, то номера исчезнут, но новые не «подтянутся» к освободившимся.
3. Параллельная вставка:
- Две транзакции одновременно вставляют строки.
- Каждая получает свой id, даже если одна потом откатится → тоже появляются пропуски.

В PostgreSQL номера генерируются через объект SEQUENCE.

Если ты вручную добавил строку с id = 9999, а sequence «застрял» на 5000.
То, когда при следующих попытках осуществить вставку строки БД дойдет до значения 9999 - этот INSERT упадёт с ошибкой: «дубликат ключа». Потому что sequence не обновляется автоматически! Sequence не смотрит на максимальный id в таблице. Он просто отдаёт своё следующее число.

Решение может быть:

ALTER SEQUENCE … RESTART WITH <нужный номер>.

На вставку строк в таблицу может быть вызов триггера. Потому что вставка строки - это новая информация. А в зависимости от новой информации у нас могут быть разная логика подсчета того или иного показателя. Например, расчет бонусов для клиента зависит от суммы заказа. Поэтому при каждой вставке в таблицу заказов будет вызван триггер по расчету бонусов для клиента.

CREATE TRIGGER bonus

AFTER INSERT ON orders

FOR EACH ROW

EXECUTE FUNCTION bonus_cnt();

Каждая новая строка вызовет bonus_cnt().
Даже если ты вставляешь 1000 строк, триггер вызовется 1000 раз.

Есть еще такое понятие как UPSERT.

UPSERT = INSERT + UPDATE, т.е. «вставить новую запись, а если такая запись уже есть — обновить существующую».

Пример: у нас есть таблица users с колонкой id. Мы хотим добавить пользователя с id = 1.

  • Если пользователя нет → вставляем.

  • Если пользователь есть → обновляем его данные.

Но такой INSERT + UPDATE в каждой СУБД реализуется по разному.
Одна и та же логика «вставить или обновить» в коде не переносится напрямую между базами. То, что называется UPSERT в PostgreSQL, будет работать иначе в MySQL и совсем иначе в SQL Server.

INSERT ... ON CONFLICT (id) DO UPDATE ... -- Вставляет запись, если id ещё нет; иначе обновляет эту запись. PostgreSQL

INSERT ... ON DUPLICATE KEY UPDATE ... -- MySQL

MERGE ... -- SQL Server

По сути, UPSERT — это концепция, а не единый универсальный оператор.

На скорость INSERT влияет наличие индексов в таблице. Чем больше индексов, тем долше будет выполняться вставка. Каждая новая строка должна обновить все индексы. При массовых загрузках индексы иногда отключают, а потом создают заново

А еще, иногда база говорит: «Вставка прошла успешно», но на диск ещё ничего не записано.

  • PostgreSQL и MySQL (InnoDB) используют write-ahead log: запись сначала идёт в журнал, потом — на диск.

  • Если прямо в этот момент выключить сервер → можно потерять часть данных.

Решается настройкой fsync, commit и уровней надёжности транзакций.

INSERT — это не просто «добавить данные». Это про индексы, блокировки, автоинкременты, батчи и даже про то, как СУБД пишет на диск.

Показать полностью 1
[моё] SQL Аналитик Аналитика База данных Выгорание экрана Новая работа Большие данные Таблица Длиннопост
5
Посты не найдены
О нас
О Пикабу Контакты Реклама Сообщить об ошибке Сообщить о нарушении законодательства Отзывы и предложения Новости Пикабу Мобильное приложение RSS
Информация
Помощь Кодекс Пикабу Команда Пикабу Конфиденциальность Правила соцсети О рекомендациях О компании
Наши проекты
Блоги Работа Промокоды Игры Курсы
Партнёры
Промокоды Биг Гик Промокоды Lamoda Промокоды Мвидео Промокоды Яндекс Маркет Промокоды Пятерочка Промокоды Aroma Butik Промокоды Яндекс Путешествия Промокоды Яндекс Еда Постила Футбол сегодня
На информационном ресурсе Pikabu.ru применяются рекомендательные технологии