SQL: Реляционные базы данных – Telegram
SQL: Реляционные базы данных
1.02K subscribers
85 photos
1 video
56 links
Канал айтишника о реляционных базах данных, SQL и модели данных. У нас тут много, очень много практических разборов))

Меня зовут Владимир Лунев (@lejnlune). Интересуюсь архитектурой систем и моделей данных.
Download Telegram
📀Заметка о том, как создать собственную одомашненную БД

Рассказываю, как создать локальную тестовую БД для практики буквально за пару минут.
Для начала качаем DBeaver, это бесплатное программное обеспечение с открытым исходным кодом, распространяемое по лицензии Apache, по сути клиент для SQL и инструмент для администрирования баз данных.

После установки запускаем приложение и в меню кликаем: Справка → Создать тестовую базу данных (всё показал на скринах последовательно). В результате получаем полноценную базу данных на SQLite.

💽 Из плюсов то, что в отличие от других систем баз данных (MySQL, Postgres и прочих) для SQLite не требует отдельного сервера. Это встраиваемый движок, который работает напрямую с файлом базы данных на диске. То есть ничего дополнительно устанавливать или конфигурировать не нужно — всё уже готово.

Но есть нюанс, у SQLite несколько ограниченный функционал по сравнению с обычными СУБД (например, нет поддержи RIGHT JOIN, FULL OUTER JOIN), однако, для практики, я думаю, это не помеха.

🖥Поэтому юзайте способ, чтобы получить представление об SQL и о том как происходит работа с БД.

P.S. на последнем скрине для проверки создал в новой БД таблицу, все ок

📱 Подписаться на канал | Курс автора по SQL DDL
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥13👾5💯2
Подготовили пост про хард скиллс в SQL совместно с @bashnya_education 👾
🔥4👾1
Forwarded from БАШНЯ
HARD SKILLS❗️

Продолжаем разбирать hard skills 🔥

Сегодня поговорим про SQL - что это такое и что спрашивают по нему на собеседованиях 👨‍💻

Делитесь этим постом с друзьями и пишите свои вопросы в комментарии ✍️

Автор поста:
Владимир Лунев, ментор в Башне

#hardskills
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥15👾6💯4
Сегодня столкнулся с гениальным описанием ошибки от СУБД.

Ок, понял 🗿
Please open Telegram to view this post
VIEW IN TELEGRAM
🤣25🗿11🌚3
👩‍💻 Материализованные представления в SQL — погружаемся глубже в теорию

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

🧊 Что такое материализованное представление?
Материализованное представление (Materialized View) — это реальный объект базы данных, содержащий предрасчитанные данные.

В отличие от обычного VIEW, здесь:
Результат запроса сохраняется как отдельная таблица;
При чтении SELECT возвращает готовые, быстро читаемые данные;
Данные не обновляются автоматически (кроме некоторых случаев, например Oracle или с триггерами);
В основном требует явного ручного обновления — REFRESH.

🧊 Архитектурно материализованное представление — это:
Текст SQL-запроса,
Физическая таблица,
Метаданные для обновления

🧊 Ключевые особенности
Сохраняет данные — Да
Обновляется автоматически — Нет (нужно REFRESH), за исключением случаев, которые рассмотрим ниже.
Быстрое выполнение SELECT — Да
Требует места на диске — Да

🧊 Общий синтаксис для создания материализованного представления:
CREATE MATERIALIZED VIEW имя_представления AS
SELECT ...
FROM ...
[WHERE ...]
[GROUP BY ...]
[ORDER BY ...];

Дополнительно можно указать:
WITH NO DATA — представление создаётся, но не заполняется (нужно REFRESH).
WITH DATA (по умолчанию) — данные вычисляются сразу при создании.

🧊 Допустим, у нас есть таблица orders, в которой хранятся заказы клиентов. Она может содержать такие поля:
-----------------------------
id SERIAL
order_date TIMESTAMP
customer_id INT
amount NUMERIC

Таблица обновляется постоянно: пользователи делают заказы, и каждая строка — это один заказ.

Часто требуется строить отчёты:
Сколько заказов было каждый день
Какова средняя сумма заказа за день

Запрос к такой таблице может быть тяжёлым, особенно если в orders миллионы строк. Поэтому создаём материализованное представление — заранее рассчитанный агрегат, чтобы анализировать среднюю сумму заказов по дням:
CREATE MATERIALIZED VIEW daily_avg_orders AS
SELECT
order_date::date AS day,
COUNT(*) AS total_orders,
AVG(amount) AS avg_order_value
FROM orders
GROUP BY day
ORDER BY day;

Что делает это материализованное представление:
После выполнения CREATE MATERIALIZED VIEW — СУБД физически сохраняет результат запроса. Теперь мы можем быстро выполнять:
SELECT * FROM daily_avg_orders;

И получать результат без перерасчёта данных каждый раз.

🛠 Обновление (refresh)
Чтобы MView оставалось актуальным, его нужно обновлять вручную или автоматически.
При ручном обновлении, чтобы обновить данные в представлении после изменений в таблице orders, выполняем:
REFRESH MATERIALIZED VIEW daily_avg_orders;

Если при создании добавили WITH NO DATA — первый REFRESH обязателен.

Можно настроить автообновление через:
Планировщик задач (например, cron);
Расписание в СУБД (например, PostgreSQL pg_cron, Oracle DBMS_SCHEDULER);
Использование триггеров или CDC

⚙️ Индексы и уникальность
Во многих СУБД материализованные представления поддерживают индексы, особенно если нужно обеспечить уникальность:
CREATE UNIQUE INDEX ON имя_представления(ключ);

Для того чтобы представление можно было обновлять инкрементально (а не полностью), часто требуется уникальный ключ.

🖥 Поддержка материализованных представлений в разных СУБД:
PostgreSQL — Полноценная, ручное обновление
Oracle — Продвинутая (есть автообновление, query rewrite)
SQL Server — Аналог: Indexed Views
MySQL — поддержки нет
ClickHouse — Аналог через MATERIALIZED VIEW с INSERT
BigQuery — Поддержка с автообновлением

👾 Где это особенно нужно?
Сложные отчёты (много JOIN, WHERE, GROUP BY) — хранит результат и не пересчитывает каждый раз
BI и дашборды — быстрые ответы
Разгрузка сервера — меньше нагрузки на исходные таблицы
Разделение хранилищ — можно экспортировать MView в другие слои данных
Медленные источники данных — данные приходят редко, но запросы часты.

Так что, материализуемся 🥁

#Views #Materialized_views #SQL

📱 Подписаться на канал | Курс автора по SQL DDL
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥13👾3💯22
Привет, нашел прикольную шпаргалку по основным джоинам от ByteByteGo.

Для инфо, JOIN в SQL — это операция, которая позволяет объединять данные из двух или более таблиц по связанному столбцу (обычно по ключу: первичному и внешнему).

Ранее писал посты про базовые джоины, однако, есть еще куча необычных join-операторов, конечно, в обиходе не все они используются часто, но кто знает, куда неофитов могут завести скитания по базе данных 😂

Скоро напишу пост про специфические джоины.
Лайк если надо 👩‍💻
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥28👾4😱2
👩‍💻 Специфические JOIN в SQL — тайные знания о соединениях

Итак, давайте разберем необычные виды join, про которые не так часто вспоминают, но они по своему прекрасны. Погнали.

💻 SELF JOIN — соединение таблицы с самой собой
SELF JOIN используется, когда нам нужно сравнить строки внутри одной и той же таблицы.
SELECT e1.name AS employee, e2.name AS manager
FROM employees e1
JOIN employees e2 ON e1.manager_id = e2.id;

Где полезен:
Связи типа «сотрудник – менеджер»
Поиск пар с определённым соотношением
Сравнение записей между собой (например, временных интервалов)

Обратить внимание:
Обязательно используйте алиасы (e1, e2) — иначе SQL не поймёт, откуда брать данные.
Производительность при больших таблицах может быть тяжёлой без индексов.

💻 CROSS JOIN — декартово произведение
Каждая строка из первой таблицы соединяется со всеми строками второй.
SELECT c.color, s.size
FROM colors c
CROSS JOIN sizes s;

Где полезен:
Генерация всех возможных комбинаций (цвет + размер, дата + товар и т.д.)
Математические переборы (в BI/аналитике)

Пример:
Таблица colors:
red
blue

Таблица sizes:
S
M
L

Результат:
color  size
red S
red M
red L
blue S
blue M
blue L

Обратить внимание:
Растёт в геометрической прогрессии — при 100 строках в каждой таблице будет 10 000 строк в результате (100×100 = 10 000 строк)!
Обычно требует явной фильтрации после соединения.

💻 NATURAL JOIN — соединение по совпадающим колонкам
Автоматически соединяет таблицы по колонкам с одинаковыми именами и типами.
SELECT *
FROM orders
NATURAL JOIN customers;

Где полезен:
Быстрые выборки, когда точно знаешь схему таблиц
Временные аналитические задачи или прототипирование

Обратить внимание:
SQL сам решает, по каким колонкам соединять! Если колонок с одинаковыми именами много, можно получить непредсказуемый результат.
Лучше не использовать в проде без явного указания колонок (ON), особенно если схему может кто-то изменить, потому что если структура изменится, все сломается.

💻 ANTI JOIN — найти то, чего нет
Ищем строки в первой таблице, у которых нет пары во второй.
На SQL делается через:
SELECT c.id
FROM customers c
LEFT JOIN orders o ON c.id = o.customer_id
WHERE o.id IS NULL;

ИЛИ:
SELECT c.id
FROM customers c
WHERE NOT EXISTS (
SELECT 1 FROM orders o WHERE o.customer_id = c.id
);


Где полезен:
Найти клиентов без заказов
Найти товары без продаж
Обнаружение "провалов" в связях

Обратить внимание:
Вариант с NOT EXISTS работает быстрее при наличии индекса
Убедитесь, что NULL действительно означает отсутствие связи, а не ошибку в данных

💻 SEMI JOIN — проверка на наличие
Найти строки из одной таблицы, у которых есть хотя бы одна пара в другой таблице, но не вытаскивать её. Забавно, но его синтаксис это JOIN без JOIN:
SELECT c.id
FROM customers c
WHERE EXISTS (
SELECT 1 FROM orders o WHERE o.customer_id = c.id
);

В отличие от INNER JOIN, мы не получаем orders.* — только customers.

Где полезен:
Проверка: есть ли связи?
Ускорение выборок, когда нужны только факты "да/нет"

Обратить внимание:
Не получится использовать данные из второй таблицы (orders) в SELECT — она просто фильтрует
Неявный тип соединения, часто путают с INNER JOIN
Не вытаскивает данные из второй таблицы.

❗️ ANTI JOIN и SEMI JOIN — неофициальные типы (в ANSI SQL их нет), реализуются через LEFT JOIN + WHERE, EXISTS и т.п.

💻 Итого:
SELF — Сравнивает записи одной таблицы
CROSS — Сравнивает все на все, юзается для генерации комбинаций
NATURAL — Сравнивает по одинаковым колонкам, используем при уверенности неизменности структуры таблиц или с ON
ANTI — Выбирает всё, что не связано, используем для поиска отсутствий
SEMI — Выбирает всё, что связано, пишется без оператора JOIN

Поддержка:
SELF, CROSS, NATURAL — есть в большинстве СУБД (PostgreSQL, MySQL, Oracle, MS SQL)
SEMI JOIN, ANTI JOIN — не имеют отдельного синтаксиса, реализуются через EXISTS / NOT EXISTS / LEFT JOIN + IS NULL
В PostgreSQL и Oracle EXISTS работает особенно эффективно благодаря индексам.

#Join #SQL

📱 Подписаться на канал
📱Мы в VK
💻 Курс автора по SQL DDL
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥146💯4
Пишу пост про SQLi*, до конца недели опубликую. В июле, скорее всего буду много говорить о безопасности БД, методах их защиты, плюс затронем выдачу и управление правами пользователей в СУБД и бэкапы.

*⚠️SQL-инъекция (SQL injection)— это атака, при которой злоумышленник внедряет вредоносный SQL-код через поля ввода, например, на сайте (логин, пароль, поисковая строка), чтобы получить несанкционированный доступ к базе данных.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥9🌚75
This media is not supported in your browser
VIEW IN TELEGRAM
Когда удалил не ту таблицу. Ну, главное, чтобы не на проде 😂
🤣16🔥5😱3🌚2
Привет, вписался в конкурс каналов с качественным авторским контентом. Потом будут голосования за лучшие посты по номинациям среди каналов и все такое — здесь @tg_contest_main. Так что, не удивляйтесь, иногда буду просить вас голосовать))

Ну а вобще, я считаю, круто, что мой канал начинает участвовать в таких штуках, для меня это своеобразный признак оценки моих стараний (как и ваши реакции) 😁
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥15🌚3💯3
😵‍💫 Как посчитать дельту к предыдущему дню в SQL

Недавно писал важный скрипт на работе, где необходимо было считать дельты внутри колонок (сегодня минус вчера). Подумал, что это очень полезное знание и решил передать его вам, моим подписчикам. Собственно вычисление между текущим и предыдущим значением внутри колонки мы и рассмотрим.

SQL-инструмент для расчёта такой дельты — оконная функция LAG()

💻 Общий синтаксис:
LAG(столбец, смещение, значение_по_умолчанию) 
OVER (PARTITION BY ... ORDER BY ...)

LAG(column) возвращает значение из предыдущей строки.
PARTITION BY — разбивка по группам (например, по пользователям или магазинам).
ORDER BY — важный момент: он определяет, по какому порядку "сравнивать".

💻 Пример: считаем дельту выручки по дням.
Допустим, у нас есть таблица sales:
sale_date   amount
2024-06-01 1000
2024-06-02 1200
2024-06-03 800

Запрос:
select
sale_date,
amount,
amount - LAG(amount) OVER (ORDER BY sale_date) AS delta
FROM sales;

Результат:
sale_date   amount  delta
2024-06-01 1000 NULL
2024-06-02 1200 200
2024-06-03 800 -400

Что происходит в запросе?
LAG(amount) OVER (ORDER BY sale_date) берёт значение за предыдущий день.
amount - LAG(...) — рассчитывает дельту
В первый день delta = NULL, ибо в первом ряду нет предыдущего значения

💻 Пример с группировкой по магазину.
Если у нас несколько магазинов в таблице store_sales:
store_id  sale_date    amount
1 2024-06-01 1000
1 2024-06-02 1200
2 2024-06-01 700
2 2024-06-02 900

Запрос:
select
store_id,
sale_date,
amount,
amount - LAG(amount) OVER (PARTITION BY store_id ORDER BY sale_date) AS delta
FROM store_sales;

PARTITION BY store_id — Разбивает данные на группы по магазину. То есть, LAG() сравнивает значения только внутри одного store_id.
ORDER BY sale_date — Определяет порядок, в котором будет вычисляться «предыдущее значение» — по дате продаж.
LAG(amount) — Возвращает значение amount из предыдущей строки (внутри своей группы и в порядке дат).
amount - LAG(amount) — Вычисляет дельту: текущий объём продаж минус предыдущий.

Что получится в результате:
store_id  sale_date   amount  delta
1 2024-06-01 1000 NULL
1 2024-06-02 1200 200
2 2024-06-01 700 NULL
2 2024-06-02 900 200


Доп.ситуация:
Если значения amount могут быть NULL, то delta будет NULL даже при корректном LAG(). Можно использовать COALESCE():
amount - COALESCE(LAG(amount) OVER (...), 0) AS delta


❗️Частые ошибки:
Нет ORDER BY в OVER — дельта будет некорректной или всегда NULL
Если даты перепутаны или дубликаты — ORDER BY может вести себя нестабильно. Лучше явно указать второй ключ (при этом в больших таблицах обязательно, читай принудительно, надо прописывать сорировку по нескольким ключевым столбцам иначе отработка запроса может давать нестабильные результаты, у вас будут буквально разные цифры при каждом перезапуске)
Нет PARTITION BY, когда нужно сравнивать внутри группы, без оператора сравнение будет идти "вперемешку", не по логике.
Сравнение разных типов данных — приводит к ошибкам или некорректным значениям.
NULL-значения — дельта может стать NULL, если предыдущее значение отсутствует.

💻 Советы:
Если нет LAG() в вашей СУБД — можно сделать JOIN таблицы самой на себя, но это медленнее.
Дельту можно не только считать, но и фильтровать по ней (например: WHERE delta > 100).
Вместо LAG() можно использовать LEAD(), чтобы сравнить с будущим значением.

#LAG #SQL

📱 Подписаться на канал
📱Мы в VK
💻 Курс автора по SQL DDL
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥187👾5
Привет, немного порассуждал над собесами и подготовкой к ним, совместно с @bashnya_education
🔥7
Forwarded from БАШНЯ
РАЗБОР РУБРИКИ НОРМ ИЛИ СТРЕМ ❗️

Владимир Лунев - наш ментор подготовил разбор, где детально рассмотрел каждый наш вопрос 🔥

Не забывайте, что уже сейчас можно записаться на занятие с ментором через нашего менеджера - @bashnya_edu 🤯

Более подробно про менторство можно узнать в нашем миниаппе 💪

#mini_app
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥17💯7👾5🤣1