SQL Academy: всё о реляционных БД и SQL
11.9K subscribers
184 photos
1 video
2 files
30 links
По всем вопросам и коммерческим предложениям писать @LadanovNick

Купить рекламу: https://telega.in/c/sqlacademyofficial

Чат студентов SQL Academy
https://t.me/sqlacademyorg
Download Telegram
Какое ограничение используется для обеспечения ссылочной целостности между таблицами?
Anonymous Quiz
81%
FOREIGN KEY
3%
DEFAULT
10%
UNIQUE
6%
NOT NULL
👍9❤2🔥2
Отличная новость ⭐️

В эту пятницу в 19:00 Денис Иванов, ведущий продуктовый аналитик, проведет открытой вебинар с очень интересно темой:

Продуктовая аналитика. Как стать уникальным кандидатом и получить заветный оффер?

На вебинаре мы обсудим:
🔹
как быть уникальным продуктовым аналитиком и сразу завоёвывать сердца на собеседованиях?
🔹как проходить собеседования и получать огромное количество офферов?
🔹 красные флаги при устройстве на первое место работы. Как не облажаться с выбором?
🔹как увеличить количество откликов для вашего резюме?

Для всех участников вебинара мы подготовили хорошую скидку на наш премиум 🎁.

Познакомиться поближе с ведущим вебинара можно в его уютном телеграмм канале @product_analytics_hub.

Подключайтесь в 19:00 13 декабря по этой ссылке
Google Meet
Please open Telegram to view this post
VIEW IN TELEGRAM
1👍12❤9🔥7
Напоминаем ⚠️

Вебинар “Продуктовая аналитика. Как стать уникальным кандидатом и получить заветный оффер?” начнется через 30 минут по ссылке:
https://meet.google.com/uwi-zgzd-ntd
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6🔥3❤1
Полезная шпаргалка по основам SQL 🧐
Please open Telegram to view this post
VIEW IN TELEGRAM
👍49❤18🔥12
Мы собрали базу вопросов по SQL для подготовки к собеседованиям! 🎯

Идеальный способ освежить знания и понять, что нужно подтянуть перед важным днем. 🧠

И для удобства сделали эти вопросы в виде карточек для запоминания, чтобы вы могли отметить вопросы выученными ✅ и больше не возвращаться к ним.

Перейти к базе вопросов по SQL
https://sql-academy.org/ru/interview-questions

Все вопросы и ответы — в открытом доступе! 📚

Присоединяйтесь к нам на GitHub и добавляйте свои вопросы или улучшайте текущие! 🌐🤝
https://github.com/SQL-Academy/ru.sql-academy
Please open Telegram to view this post
VIEW IN TELEGRAM
👍33🔥20❤5👎1
📂 Временные таблицы
Временные таблицы позволяют временно хранить данные в текущей сессии. Они полезны для работы с промежуточными результатами и оптимизации сложных запросов. Такие таблицы автоматически удаляются после завершения соединения с базой данных.

🔧 Основные особенности:
🔹 Создаются с помощью команды CREATE TEMPORARY TABLE
🔹 Существуют только в рамках текущей сессии
🔹 Разные сессии могут использовать таблицы с одинаковыми именами

📚 Пример: создание временной таблицы
Предположим, у вас есть таблица orders, и вы хотите узнать, какие клиенты сделали заказы на сумму более 1000 евро.

CREATE TEMPORARY TABLE temp_high_value_orders AS
SELECT customer_id, SUM(amount) AS total_amount
FROM orders
GROUP BY customer_id
HAVING total_amount > 1000;


🔍 Что делает этот запрос?
🔹 Создает временную таблицу temp_high_value_orders.
🔹 Сохраняет информацию о клиентах и сумме их заказов.
🔹 Оставляет только тех клиентов, чья сумма заказов превышает 1000.

🤔 Зачем использовать временные таблицы?

✅ Уменьшить нагрузку на базу данных.
Сложные вычисления выполняются один раз, а результаты сохраняются для последующих запросов.

✅ Упростить основной запрос.
После создания временной таблицы можно использовать ее как обычную таблицу:

SELECT c.name, t.total_amount
FROM customers c
JOIN temp_high_value_orders t ON c.id = t.customer_id;
Please open Telegram to view this post
VIEW IN TELEGRAM
👍22🔥10❤9
Подзапросы (Subqueries) в SQL ⭐️
Подзапрос (Subquery) — это запрос внутри другого запроса. Он выполняется первым и передает результат основному запросу.

🔍 Некоторые виды подзапросов:

🔹 В SELECT — используется для получения дополнительных данных:

SELECT name,
(SELECT COUNT(*) FROM orders WHERE customer_id = customers.id) AS order_count
FROM customers;


🔹 В WHERE — используется для фильтрации:

SELECT name FROM products
WHERE price > (SELECT AVG(price) FROM products);


🔹 В FROM — подзапрос как временная таблица:

SELECT avg_price FROM
(SELECT AVG(price) AS avg_price FROM products) AS temp;
Please open Telegram to view this post
VIEW IN TELEGRAM
👍50❤14🔥7
🌟 Считаем возраст человека правильно 🌟

Вы когда-нибудь задумывались, как правильно вычислить возраст человека в SQL? 🤔 Может показаться, что всё просто: возьмём текущий год, отнимем год рождения, и вуаля! Но ой, подстерегает соблазн ошибки! 😈

🚫 Неправильный подход:

SELECT YEAR(NOW()) - YEAR('2003-07-03 14:10:26');

Проблема такого подхода в том, что он не учитывает был ли день рождения у данного человека в этом году или ещё нет. То есть, если на момент запроса уже наступило 3-е июля (07-03), то человек отпраздновал свой день рождения и ему уже 21 лет, иначе ему по-прежнему 20 года. Разница функций YEAR тут будет бесполезна — в обоих случаях она даст 21 лет.

🤔 Что же делать? Мы могли бы пойти по пути вычисления разницы в днях и деления на 365:

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
👍78❤20🔥14👎2
CASE WHEN: Условные выражения в SELECT ✨
Иногда нужно «разделить» данные по условию прямо внутри запроса, не меняя структуру таблицы и не создавая дополнительные поля. И тут на помощь приходит CASE WHEN!

Что это такое?
CASE WHEN — это оператор, который позволяет писать логику «если… то… иначе…» в SELECT, WHERE, ORDER BY и других частях SQL-запроса.

Пример использования
Допустим, у нас есть таблица products с колонками: name (название товара) и price (цена). Нужно вывести для каждого товара метку, говорящую о ценовом уровне:

SELECT
name,
price,
CASE
WHEN price < 50 THEN 'Дешево'
WHEN price BETWEEN 50 AND 100 THEN 'Средне'
ELSE 'Дорого'
END AS price_label
FROM products;


Что тут происходит?
1. CASE проверяет цену в каждой строке:
🔹Если цена < 50, то подставляем строку 'Дешево'.
🔹Если цена между 50 и 100, получаем 'Средне'.
🔹И во всех остальных случаях — 'Дорого'.
2. Результат помещаем в новый столбец — price_label.

Зачем это нужно?
🔹Быстрая категоризация данных без изменений в самой таблице.
🔹Условная логика в запросах: выводим разные значения в зависимости от условий.
🔹Упрощает отчёты и помогает строить «человеко-понятные» выводы данных.

Попрактиковаться в написание запроса с использование CASE оператора можно в заданиях для самопроверки по ссылке
https://sql-academy.org/ru/guide/case-expression
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥40👍11❤5💘1
Генерируемые столбцы (Generated Columns) в MySQL — это столбцы, значение которых вычисляется автоматически на основе других столбцов в таблице. Это очень удобно, когда нужно всегда иметь «актуальную» производную величину (например, итоговую стоимость, индекс массы тела, коэффициент, результат арифметических операций и т.д.), при этом не писать лишний код или триггеры. 🔮

В чём суть? ⚙️
Вместо того чтобы хранить формулу в приложении, мы «встраиваем» логику прямо в таблицу. При обновлении данных в базовых полях вычисляемый столбец тоже меняется.

Два вида генерируемых столбцов:
🔹VIRTUAL (виртуальный)
Значение вычисляется «на лету» при выборе из таблицы и не хранится физически.
🔹STORED (сохранённый)
Значение сохраняется в таблице и обновляется при изменении данных. Имеет свой физический размер, но и доступ к нему быстрее (особенно при частых запросах).

Пример создания таблицы с генерируемым столбцом
Предположим, у нас есть таблица для хранения товаров. В ней мы хотим автоматически высчитывать итоговую стоимость (total_cost) как произведение цены price на количество quantity.

CREATE TABLE items (
id INT AUTO_INCREMENT PRIMARY KEY,
price DECIMAL(10,2),
quantity INT,
-- Генерируемый столбец, который будет хранить итоговую стоимость
total_cost DECIMAL(10,2) AS (price * quantity) STORED
);

🔹AS (price * quantity) — формула, по которой будет вычисляться столбец total_cost.
🔹STORED означает, что итоговая стоимость будет записываться в таблицу и быстренько выдаваться из физического хранения.
🔹При вставке или обновлении записи MySQL сама позаботится о том, чтобы total_cost пересчитался.

А если сделать виртуальный столбец? 💡
Чтобы не занимать место на диске, используем VIRTUAL:

CREATE TABLE items_virtual (
id INT AUTO_INCREMENT PRIMARY KEY,
price DECIMAL(10,2),
quantity INT,
total_cost DECIMAL(10,2)
AS (price * quantity) VIRTUAL
);

🔹 Поле total_cost не хранится физически. Оно вычисляется при каждом чтении строки.
🔹При частом чтении большого количества строк запросы могут работать чуть медленнее, ведь каждый раз идёт пересчёт.
🔹Зато при редких выборках и частых обновлениях виртуальный столбец может быть выгоднее, так как не используется дополнительное место на хранение.

Индексация и ограничения 🔑
🔹STORED столбцы можно индексировать, а значит, быстрее искать по ним.
🔹VIRTUAL столбцы индексировать нельзя

Подводим итоги 🏆
🔹Генерируемые столбцы избавляют от необходимости самостоятельно следить за обновлением вычисляемых значений.
🔹Выбор между VIRTUAL и STORED зависит от частоты чтения/записи, а также необходимости индексации.
🔹Такой подход упрощает архитектуру БД и код приложения: формула одна, лежит «рядом с данными», все операции прозрачны и понятны.

Если вам нужно ускорить расчёт «сложной формулы» или хранить результат для аналитических задач — выбирайте STORED. Если поле лишь вспомогательное, используйте VIRTUAL.
👍21❤10🔥8
📊 Медиана в SQL: почему она важнее среднего?
Среднее арифметическое (AVG()) часто используется для анализа данных, но иногда оно даёт искажённые результаты.

Например, представьте, что у нас есть 11 сотрудников:
🔹10 человек получают 40 000 💰
🔹1 человек получает 5 000 000 💰

Если посчитать среднюю зарплату, получится:

SELECT AVG(salary) FROM salaries;

👉 Средняя зарплата: 490 000

Но разве это отражает реальность? Большинство сотрудников получают 40 000, а один выбивает статистику.

✅ Медиана (MEDIAN) — это значение, которое делит отсортированные данные пополам: половина значений меньше, половина больше. В данном случае медиана = 40 000, что лучше отражает ситуацию.

📌 Как посчитать медиану в MySQL?
В отличие от AVG(), в MySQL нет встроенной функции MEDIAN(), но её можно посчитать разными способами.

1️⃣ Метод через ORDER BY LIMIT (для нечётного количества записей)
Если записей нечётное количество, медиана — это значение в центре списка:

SELECT salary FROM salaries
ORDER BY salary
LIMIT 1 OFFSET (SELECT COUNT(*) FROM salaries) / 2;

⚠️ Минус: Работает только для нечётного количества записей.

2️⃣ Метод через ROW_NUMBER() (универсальный способ)
Этот метод работает и для чётного, и для нечётного количества записей:

WITH ordered AS (
SELECT salary, ROW_NUMBER() OVER (ORDER BY salary) AS rn,
COUNT(*) OVER () AS total
FROM salaries
)
SELECT AVG(salary) FROM ordered
WHERE rn IN (FLOOR((total + 1) / 2), CEIL((total + 1) / 2));

🔹 Мы нумеруем строки с ROW_NUMBER().
🔹 Выбираем одно или два центральных значения.
🔹 Берём их среднее (AVG()) — для чётного числа записей берётся среднее двух центральных значений.

🏆 Итог
✅ Медиана полезнее среднего арифметического, когда есть выбросы в данных.
✅ В MySQL нет встроенной MEDIAN(), но её можно вычислить с ROW_NUMBER().
✅ Используйте медиану, если хотите честную аналитику! 🚀
Please open Telegram to view this post
VIEW IN TELEGRAM
👍42❤22🔥4🤩2
🔐 Как хранить пароли в базе данных? 🤔
Если вы храните пароли в базе как обычный текст — вы в опасности! 🚨 Это одна из самых больших ошибок в безопасности. Давайте разберёмся, как правильно хранить пароли в MySQL, чтобы ваши пользователи были защищены! 🔒

🚫 Плохие способы хранения паролей
1. Хранение пароля в открытом виде:

INSERT INTO users (username, password) VALUES ('kolya', 'mypassword123');

👉 Это ужасная практика! Если база данных утечёт, злоумышленники сразу получат доступ ко всем аккаунтам! 😱

2. Использование MD5/SHA1:

INSERT INTO users (username, password) VALUES ('kolya', 'bff149a0b87f5b0e00d9dd364e9ddaa0');

👉 MD5 и SHA1 устарели и больше не считаются безопасными! Их можно взломать с помощью радужных таблиц (rainbow tables) 🌈 или перебора (brute force). 🛑

✅ Хороший способ: хеширование паролей 🔒
Лучший способ защитить пароли — использовать bcrypt или Argon2. В MySQL есть встроенная функция PASSWORD(), но её не рекомендуют использовать, так как она небезопасна!
😕 Вместо этого используем bcrypt. 🎉

🔹 Как хешировать пароль в Python (рекомендуется)

import bcrypt

password = b'mypassword123'
hashed_password = bcrypt.hashpw(password, bcrypt.gensalt())
print(hashed_password)

🔹 Как хранить хеш в базе:

CREATE TABLE users (
id INT PRIMARY KEY,
username VARCHAR(255) UNIQUE,
password_hash VARCHAR(255)
);

INSERT INTO users (username, password_hash) VALUES ('kolya', '$2y$10$abcdefghijABCDEFGHIJ1234567890');

👉 Здесь password_hash хранит уже захешированный пароль, а не сам пароль! 🔐

🔓 Как проверить пароль при входе?
В Python:

if bcrypt.checkpw(b'mypassword123', stored_hash.encode()):
print('Пароль верный! ✅')
else:
print('Неправильный пароль! ❌')


🛡 Итог
❌ НЕ храните пароли в открытом виде! 🚫
❌ НЕ используйте MD5 или SHA1! ❗️
✅ ИСПОЛЬЗУЙТЕ bcrypt или Argon2! 🔥
✅ ИСПОЛЬЗУЙТЕ bcrypt.hashpw() и bcrypt.checkpw() в Python! 🏆

Следуя этим правилам, вы защитите данные пользователей и сделаете свой сервис безопаснее! 🔒💪
Please open Telegram to view this post
VIEW IN TELEGRAM
👍36❤12🔥8
Как устроены хранилища MySQL: InnoDB vs MyISAM vs MEMORY 🏗️
Когда вы создаёте таблицу в MySQL, у неё есть так называемый движок хранения (storage engine). Это то, как MySQL управляет данными внутри таблицы: где их хранить, как их обновлять и как быстро к ним обращаться.

В MySQL есть несколько движков, но самые популярные:
🔹InnoDB — стандартный и самый надёжный вариант 🔥
🔹MyISAM — старый, быстрый, но без транзакций ⚡
🔹MEMORY — для супербыстрых временных таблиц 🧠

Давайте разберёмся, в чём их различия и когда какой использовать.

🔥 InnoDB — современный стандарт
InnoDB — это основной и рекомендуемый движок в MySQL. Он поддерживает транзакции, обеспечивает целостность данных и отлично подходит для больших нагрузок.

Основные особенности:
✅ Поддержка транзакций — если что-то пошло не так, можно откатить изменения (ROLLBACK).
✅ Поддержка внешних ключей — можно строить связи между таблицами (FOREIGN KEY).
✅ Блокировка на уровне строк — если обновляется одна строка, другие остаются доступными.
✅ Хранит данные в кластеризованном индексе — быстрее работает с PRIMARY KEY.

🛠 Где используется?
🔹В интернет-магазинах, CRM-системах, SaaS-проектах.
🔹Там, где важна целостность данных (например, банковские операции).
🔹Если нужна высокая скорость чтения и записи одновременно.

⚡ MyISAM — быстрый, но устаревший
MyISAM был основным движком в MySQL до версии 5.5. Он работает быстрее, но не поддерживает транзакции.

Основные особенности:
✅ Очень быстрое чтение данных — идеален для аналитики.
✅ Легче в администрировании — структура проще, чем у InnoDB.

❌ Минусы:
🔹 Нет транзакций — если сервер упадёт во время записи, можно потерять данные.
🔹 Блокировка на уровне таблицы — если обновляется одна строка, вся таблица заблокирована.
🔹 Нет внешних ключей — нельзя строить сложные связи между таблицами.

🛠 Где используется?
🔹В системах, где важнее скорость чтения, а не записи (например, блоги, статистика).
🔹В проектах, где потеря данных не критична.
🔹Сейчас почти не используется, потому что InnoDB во многом его заменил.

🧠 MEMORY — супербыстрые временные таблицы
MEMORY хранит данные не на диске, а в оперативной памяти (RAM). Это делает его невероятно быстрым, но с одной важной особенностью: при перезапуске MySQL все данные исчезают!

Основные особенности:
✅ Молниеносная скорость — идеально для временных данных.
✅ Нет нагрузки на диск — всё работает в оперативке.
✅ Отлично подходит для кэша — можно временно хранить результаты сложных запросов.

❌ Минусы:
🔹Данные исчезают при рестарте MySQL.
🔹Не поддерживает TEXT и BLOB (нельзя хранить большие строки и файлы).
🔹Ограничение на размер — зависит от объёма оперативной памяти.

🛠 Где используется?
🔹Временные таблицы для отчётов.
🔹Кэширование данных, которые часто запрашиваются.
🔹Для промежуточных вычислений.

🏆 Какой движок выбрать?
🔹Если не знаете, что выбрать — берите InnoDB. Он безопасный, поддерживает транзакции и гибкий.
🔹MyISAM хорош только для устаревших проектов, но сейчас почти не используется.
🔹MEMORY подходит для временных данных, если они не должны сохраняться после перезапуска сервера.

Теперь вы знаете, как устроены хранилища MySQL и какой движок выбрать для своего проекта! 🚀
1👍15❤3🔥3🤩1