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

Меня зовут Владимир Лунев (@lejnlune). Интересуюсь архитектурой систем и моделей данных.
Download Telegram
🧊 Айсберг SQL

Однажды, наткнулся на забавный мем, который с каждым уровнем становится все сложнее и страшнее, посмеялся и забыл. А недавно нашёл статью на Хабр и оказалось, что у мема есть реальное практическое применение, ведь он, по сути, этап за этапом разбирает взаимодействие через SQL с СУБД PostgreSQL, а автор мема SQL-разработчик Джордан Льюис.

Так что можно использовать мем, чтобы выстроить свой путь изучения SQL, как методичку))

На этой неделе, кстати, опубликую пост, как быстро погрузиться в SQL, если вы новичок, и за пару недель (или меньше) достичь гордого уровня junior, минимально необходимого для прохождения собеседований.
🔥28👾4🌚31
🪙Junior-ready: выучить SQL и пройти собесы. Часть 1/2

Набросал своеобразную карту навыков и знаний необходимых для базового, но уверенного понимания работы с реляционными БД. У поста будет еще вторая часть, больше про сами собесы и задачки на них. А пока основы:

📤 Освойте синтаксис базовых SQL-запросов.

Начинать нужно с основ. Вы должны понимать, как извлекать данные из таблиц и как управлять результатом запроса. Разберитесь с базовыми конструкциями:
SELECT — выбор данных (всех или конкретных столбцов)
FROM — указание таблицы, из которой берутся данные
WHERE — фильтрация строк по заданным условиям
AND / OR — логические связки условий
ORDER BY — сортировка результатов
LIMIT — ограничение количества строк
LIKE, IN, BETWEEN — работа с шаблонами, списками и диапазонами

Уже на этом этапе вы сможете решать до 40% практических задач, особенно из области аналитики или SQL-тестов на позицию junior.

📤 Понимание соединений таблиц (JOIN).

В большинстве реальных задач данные разбросаны по нескольким таблицам. Чтобы собрать полную картину, нужно уметь соединять таблицы между собой. Разберитесь с основными типами соединений:
INNER JOIN — возвращает только те строки, где есть совпадения в обеих таблицах
LEFT JOIN — сохраняет все строки из левой таблицы, даже если нет совпадений в правой
RIGHT JOIN и FULL JOIN — менее распространены, но могут пригодиться в BI и отчётности

Понимание JOIN — обязательный навык. Ошибки в соединениях часто приводят к неверным результатам и срезают кандидатов на собеседованиях.

📤 Агрегатные функции и группировка.

Вам нужно научиться считать и группировать данные, это важно для аналитики через SQL. Изучите:
Агрегатные функции: SUM, AVG, MIN, MAX, COUNT
GROUP BY — группировка строк по значениям одного или нескольких столбцов
HAVING — фильтрация уже агрегированных результатов (в отличие от WHERE)

На этой базе строится вся аналитика: подсчёты по клиентам, категориям, регионам и т.д.

📤 Работа с датами и временем

Многие задачи связаны с анализом по дням, неделям, месяцам. Изучите:
Форматы даты и времени в SQL (DATE, TIMESTAMP)
Функции: NOW(), CURRENT_DATE, DATE_TRUNC, EXTRACT, AGE, INTERVAL
Фильтрация по дате, расчёты интервалов, группировка по датам

Это часто встречается в SQL-задачах.

📤 Вложенные запросы и CTE.

Часто задачи требуют промежуточных расчётов или сложной логики. Тут пригодятся:
Подзапросы — вложенные запросы, которые возвращают значения для фильтрации, расчётов или сравнения.
CTE (Common Table Expressions) — конструкции с WITH, которые позволяют сделать код читаемым.

Вложенные конструкции активно используются в продвинутой аналитике, автоматизированных отчётах и сложных тестовых заданиях.

📤 Практика — каждый день, ну если не каждый, то как можно чаще.
Что из ресурсов могу посоветовать:
Stepik — «Интерактивный тренажер по SQL» (по мне так годный, бесплатный курс)
Интерактивный тренажёр по SQL — SQL Academy (бесплатный тренажер, с норм задачками)
Рекомендую запилить себе домашнюю БД и делать в ней, что угодно. Моя инструкция тут

📤 Что важно из теории. Изучите и запомните:

Что такое реляционная модель данных
Чем различаются первичный ключ, внешний ключ и уникальные ограничения
Что такое NULL и как с ним работают сравнения (спойлер: NULL = NULL — это не TRUE)
Что такое индексы, как они ускоряют выборку и когда не работают
Как интерпретировать план выполнения запроса (EXPLAIN), каков порядок выполнения запроса и порядок написания операторов
Что такое дубли в данных и почему они часто возникают при неосторожных JOIN'ах

Это то, что помогает не просто писать код, а реально понимать, как устроен SQL и базы данных.

Итог
Для уверенного уровня Junior важно:
Уметь писать SELECT с фильтрами
Работать с JOIN и группировками
Использовать агрегатные функции, подзапросы и CTE
Понимать даты, индексы и планы выполнения
Проверять запросы на корректность и скорость
Базово знать теорию реляционных БД

Продолжение следует 🥁

#Junior #SQL

📱 Подписаться на канал
💻 Курс автора по SQL DDL
🌎 Мой ИТ-стартап
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥24👾118💯2🌚1
Никогда не забывайте про WHERE 😂
🤣22💯137😱2
Основы по работе с датами в SQL. Часть 1/3

Работа с датами и временем — это неотъемлемая часть большинства SQL-запросов. Независимо от того, анализируете ли вы продажи по месяцам, фильтруете данные за определённый период или рассчитываете сроки выполнения задач — понимание работы с датами просто необходимо. Перед тем как начинать работать с датами, важно понять, как именно они хранятся в различных СУБД (определите вашу и погуглите какой синтаксис она приветствует), это поможет избежать множества ошибок и неожиданностей.

Основные типы данных для хранения дат:

DATE — хранит только дату без времени
Формат: YYYY-MM-DD (например: 2024-03-15)
Диапазон: от 1000-01-01 до 9999-12-31
Использование: когда важна только дата (день рождения, дата регистрации)

TIME — хранит только время суток
Формат: HH:MM:SS (например: 14:30:25)
Может включать: микросекунды HH:MM:SS.ffffff
Использование: время начала/окончания рабочего дня, длительность процессов

DATETIME — хранит дату и время вместе
Формат: YYYY-MM-DD HH:MM:SS (например: 2024-03-15 14:30:25)
Диапазон: от 1000-01-01 00:00:00 до 9999-12-31 23:59:59
Использование: временные метки событий, логи

TIMESTAMP — похож на DATETIME, но с важными отличиями:
Диапазон: от 1970-01-01 00:00:01 UTC до 2038-01-19 03:14:07 UTC
Автоматическое обновление: может обновляться при изменении строки
Часовой пояс: часто зависит от настроек сервера
Использование: когда важна временная зона и автоматическое обновление

Дальше распишу функционал внутри кода, для наглядности.

Функции получения текущего времени.
Эти функции используются постоянно — для фильтрации свежих данных, создания временных меток, сравнения с прошлыми значениями.
-- Получаем только текущую дату (без времени)
-- Результат будет примерно таким: 2024-03-15
SELECT CURRENT_DATE;
-- Альтернатива:
SELECT CURDATE(); -- То же самое в MySQL

-- Получаем текущую дату и время
-- Результат будет примерно таким: 2024-03-15 16:45:30
SELECT NOW();
-- Альтернативы:
SELECT CURRENT_TIMESTAMP; -- То же самое, что и NOW()
SELECT LOCALTIME(); -- В некоторых СУБД
SELECT LOCALTIMESTAMP(); -- В некоторых СУБД

-- Получаем только текущее время (без даты)
-- Результат будет примерно таким: 16:45:30
SELECT CURRENT_TIME;
-- Альтернатива:
SELECT CURTIME(); -- То же самое в MySQL


Извлечение отдельных компонентов даты и времени.
Часто нужно получить отдельные части даты — год, месяц, день и т.д. Для этого используются функции извлечения.
-- Представим, что у нас есть таблица orders с полем created_at
-- Значение created_at: '2024-03-15 14:30:25'

SELECT
created_at, -- Исходное значение: 2024-03-15 14:30:25

-- Извлекаем год из даты
-- Результат: 2024
EXTRACT(YEAR FROM created_at) AS order_year,

-- Извлекаем месяц из даты
-- Результат: 3 (март)
EXTRACT(MONTH FROM created_at) AS order_month,

-- Извлекаем день месяца
-- Результат: 15
EXTRACT(DAY FROM created_at) AS order_day,

-- Извлекаем день недели (0 = воскресенье, 1 = понедельник, ...)
-- Результат: 6 (суббота)
EXTRACT(DOW FROM created_at) AS day_of_week,

-- Извлекаем день года (1-365/366)
-- Результат: 75 (15 марта — 75-й день года)
EXTRACT(DOY FROM created_at) AS day_of_year,

-- Извлекаем час
-- Результат: 14
EXTRACT(HOUR FROM created_at) AS order_hour,

-- Извлекаем минуты
-- Результат: 30
EXTRACT(MINUTE FROM created_at) AS order_minute,

-- Извлекаем секунды
-- Результат: 25
EXTRACT(SECOND FROM created_at) AS order_second,

-- Извлекаем квартал года (1-4)
-- Результат: 1 (первый квартал)
EXTRACT(QUARTER FROM created_at) AS quarter,

-- Извлекаем номер недели года (1-53)
-- Результат: 11
EXTRACT(WEEK FROM created_at) AS week_number

FROM orders
WHERE id = 123; -- Для примера берём конкретную запись


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

#SQL #Даты

📱 Подписаться на канал
💻 Курс автора по SQL DDL
🌎 Мой ИТ-стартап
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥238👾4💯1
Основы по работе с датами в SQL. Часть 2/3

Привет, продолжаем разбор основ начатый в предыдущем посте. Там мы разобрали:

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

Для инфо синтаксис в коде постов пишу для PostgreSQL (как популярной промышленной СУБД, для других логика похожа, но синтаксис может отличаться, гуглите)

Арифметика с датами: работа с интервалами

SQL позволяет выполнять математические операции с датами — добавлять/вычитать дни, месяцы, годы и другие временные интервалы.
-- Предположим, у нас есть дата: '2024-03-15 14:30:25'

SELECT
created_at, -- Исходная дата: 2024-03-15 14:30:25

-- Добавляем 7 дней (также можно и с месяцами - '2 months')
-- Результат: 2024-03-22 14:30:25
created_at + INTERVAL '7 days' AS one_week_later,

-- Вычитаем 3 дня
-- Результат: 2024-03-12 14:30:25
created_at - INTERVAL '3 days' AS three_days_ago,

-- Добавляем 1 год
-- Результат: 2025-03-15 14:30:25
created_at + INTERVAL '1 year' AS next_year,

-- Добавляем 3 часа
-- Результат: 2024-03-15 17:30:25
created_at + INTERVAL '3 hours' AS three_hours_later,

-- Добавляем 30 минут
-- Результат: 2024-03-15 15:00:25
created_at + INTERVAL '30 minutes' AS thirty_minutes_later,

-- Комбинируем интервалы
-- Результат: 2025-04-22 17:45:25 (через 1 год, 1 месяц, 7 дней, 3 часа, 15 минут)
created_at + INTERVAL '1 year' + INTERVAL '1 month' + INTERVAL '7 days' +
INTERVAL '3 hours' + INTERVAL '15 minutes' AS complex_interval
FROM orders
WHERE id = 123;


Вычисление разницы между датами

Часто нужно узнать, сколько времени прошло между двумя событиями — для этого есть специальные функции.
-- Считаем разницу между двумя конкретными датами в днях
-- Результат: 7 (разница в днях между 15 марта и 22 марта)
SELECT '2024-03-22'::date - '2024-03-15'::date AS days_difference;

-- Считаем разницу между датой заказа и текущей датой
SELECT
created_at, -- Дата создания заказа

-- Текущая дата
CURRENT_DATE,

-- Сколько дней прошло с момента создания заказа
-- Если результат отрицательный - заказ из будущего
-- Если положительный - сколько дней прошло
CURRENT_DATE - created_at::date AS days_since_order,

-- Альтернативный способ: сколько дней до будущей даты
'2024-12-31'::date - CURRENT_DATE AS days_until_new_year

FROM orders
WHERE id = 123;


Форматирование дат для отображения

Иногда нужно представить дату в определённом формате — для отчётов, пользовательского интерфейса и т.д.
-- Исходная дата: '2024-03-15 14:30:25'
-- Хотим получить различные форматы отображения

SELECT
created_at, -- Исходное значение: 2024-03-15 14:30:25

-- Форматируем как: 15.03.2024
-- DD = день (01-31), MM = месяц (01-12), YYYY = год (4 цифры)
TO_CHAR(created_at, 'DD.MM.YYYY') AS formatted_date_1,

-- Форматируем как: 15/03/24 (день/месяц/год 2 цифры)
-- YY = год (2 цифры)
TO_CHAR(created_at, 'DD/MM/YY') AS formatted_date_2,

-- Форматируем как: 15 марта 2024
-- Month = полное название месяца
TO_CHAR(created_at, 'DD Month YYYY') AS formatted_date_3,

-- Форматируем как: Пятница, 15 марта 2024
-- Day = полное название дня недели, Month = полное название месяца
TO_CHAR(created_at, 'Day, DD Month YYYY') AS formatted_date_4,

-- Форматируем как: 2024-03-15 (ISO формат)
TO_CHAR(created_at, 'YYYY-MM-DD') AS iso_date,

-- Форматируем время как: 14:30
-- HH24 = час (00-23), MI = минуты (00-59)
TO_CHAR(created_at, 'HH24:MI') AS time_only,

-- Форматируем как: 15.03.2024 14:30
TO_CHAR(created_at, 'DD.MM.YYYY HH24:MI') AS datetime_formatted

FROM orders
WHERE id = 123;


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

#SQL #Даты

📱 Подписаться на канал
💻 Курс автора по SQL DDL
🌎 Мой ИТ-стартап
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥14🤣7👾64🤯1
👩‍💻 Он создал MySQL — и потерял миллиарды. История, о которой редко рассказывают.

Привет, сегодня лайтовая история про создателя 2-х весьма популярных СУБД, решил писать больше такого контента, а не только делать разборы запросов)

Итак, слышал про MySQL?
Это не просто СУБД — это фундамент, на котором вырос весь интернет 2000-х. А придумал её финский программист — почти в одиночку. Его зовут Микаэль "Монти" Видениус.

❗️ Кто такой Монти
Родился в 1962 году в Хельсинки. В 4 года попал в аварию и всю жизнь хромает. В школе спорт не шёл, зато компьютеры стали главным увлечением.
Первый код написал в 1970-х, а в 19 лет уже делал программы для бизнеса.
Учился в Хельсинкском техническом университете, не окончив его, в 1981 году начал работать в компании Тапио Лааксо.
В 1985 году совместно с Аланом Ларссом основал компанию TCX DataKonsult. В 1994 году вместе с Давидом Аксмарком приступил к созданию первой версии MySQL. В следующем году совместно с Ларрсом и Аксмарком основал компанию MySQL AB, нацеленную на коммерциализацию продукта.

❗️ Как это было
Монти получил от клиента просьбу сделать простую базу «для веба», в результате размышлений над задачей родилась идея новой СУБД. Он берёт концепт движка mSQL, переписывает его с нуля и создаёт MySQL — базу, которая изменит интернет. Монти называет ее в честь дочери: My + SQL.

❗️ MySQL он выкладывает в сеть:
бесплатно,
с открытым кодом,
с установкой «за 5 минут».

Разработчики в восторге: «Наконец-то альтернатива Oracle, за которую не нужно платить тысячи долларов!»
MySQL становится стандартом веба.

❗️ Как потерять миллиарды
2008 год. MySQL используют Google, NASA, Mail Group, «Яндекс».
Монти был техническим директором MySQL AB вплоть до её продажи компании Sun Microsystems в январе 2008 года.
Компания Sun покупает MySQL AB за $1 млрд. А Монти зарабатывает на сделке около 16,6 миллионов евро.

Казалось бы — успех! Но:
Монти получил лишь часть от сделки — и упустил шанс стать одним из самых богатых людей в IT. А ведь MySQL стал фундаментом интернета — его ценность сегодня могла бы исчисляться десятками миллиардов.
А вскоре Sun поглощает… Oracle — главный конкурент MySQL. И вместе с потенциальными миллиардами уходит контроль над судьбой проекта.

❗️ Восстание
12 декабря 2009 года Монти обратился к сообществу с просьбой написать в Еврокомиссию письма за предотвращение поглощения Sun Microsystems корпорацией Oracle в связи с возможной монополизацией рынка СУБД, так как в результате сделки Oracle получала права на MySQL и активы MySQL AB, но не смотря на это, поглощение было одобрено.
Монти решает: «Раз так — будет новая база». Берёт открытую версию MySQL и делает форк. Называет его в честь младшей дочери — MariaDB.
По задумке MariaDB — это MySQL, только свободнее. Без Oracle. С открытым будущим и со своими улучшениями — от скорости до масштабируемости. Сегодня её используют Wikipedia, Google Cloud, «СберТех».
Однако, со временем архитектуры разошлись. Где-то MariaDB быстрее, где-то — MySQL. MariaDB добавила много нового (например, движок ColumnStore, улучшенную репликацию), но и MySQL не стоит на месте и пытается активно конкурировать с другими СУБД сегмента.

❗️ А что Oracle?
Oracle вынужден развивать MySQL: слишком много зависимых проектов. А MariaDB растёт и отбирает долю рынка.

❗️ Что сейчас с Монти?
Живёт в Финляндии, пишет код, ему за 60. Не миллиардер. Просто инженер, который сделал интернет и работу с БД удобнее.

❗️ Подведем мораль?
Можно создать продукт, который меняет мир — и не заработать на нём.
Можно лишиться своего детища — и вырастить новое, ещё сильнее.
А можно просто продолжать кодить. И быть счастливым.

А ты бы выбрал миллиарды — или свободу кода?

#SQL #Факты

📱 Подписаться на канал
💻 Курс автора по SQL DDL
🌎 Мой ИТ-стартап
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥24😱7👾43💯1
Всем привет)) Совместно @simulative_official организуем буткемп по SQL, регистрация доступна уже сейчас, буду рад вашему участию 👩‍💻
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥6👾43💯1
Forwarded from Simulative
Привет, аналитики! Меня зовут Владимир Лунев. Более 5 лет я работаю в IT как бизнес- и системный аналитик.

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

Я часто сталкивался с задачами, где точность и скорость обработки данных имели критическое значение: приходилось быстро выявлять скрытые ошибки, обеспечивать корректность бизнес-отчётов и автоматизировать расчёты ключевых показателей.


Несколько кейсов из моей работы:

👑 Оптимизировал отчёт и сократил время его выполнения с 3 часов, до 30 минут, не переписывая бизнес-логику, а разобрав EXPLAIN и исправив ошибки SQL-запросов.
👑 Построил систему контроля качества данных на основании проверочных скриптов, которая автоматически ловила дубли, NULL-ловушки и логические противоречия до попадания информации в отчёты.
👑 Разработал автоматизированный процесс агрегации и расчёта KPI для сети магазинов, позволивший ежедневно получать корректные метрики без ошибок.

Я буду ведущим SQL-буткемпа — практикума, где вы получите реальные навыки, которые работают в боевых проектах бизнеса. В рамках буткемпа мы разберём:

Оптимизацию запросов в SQL — разбор EXPLAIN, выявление «тормозящих» мест, исправление лишних подзапросов и «фантомных» строк для ускорения критичных бизнес-отчётов и выгрузок.
Контроль качества данных — научимся писать кастомные скрипты проверок данных для точных и надёжных данных.
Прогнозы и тренды — построение когорт, скользящих метрик, lag/lead-анализ и простые линейные прогнозы для точного планирования.
Сценарный анализ «что если» — моделирование альтернатив через параметризацию, temp-таблицы и CTE, автоматизация расчётов для оценки влияния изменений на ключевые показатели.
Агрегацию данных и полезные бизнес-метрики — расчёт growth, hitrate, долей, YoY, контроль перекосов и проведение A/B-анализов для оценки эффективности решений.
Рекурсию и последовательности — поработаем с деревьями parent-child, обходом графов, кластеризацией и сегментацией пользовательских действий для глубокого анализа процессов.

Формат: много практики на кейсах и задачах из IT-проектов и немного сопутствующей теории.

Буткемп будет полезен аналитикам, data-engineers, backend-разработчикам, а также всем, кто работает с массивами данных, строит отчёты и хочет улучшить навыки владения SQL.


Если вы хотите писать SQL-запросы так, чтобы данные реально работали на вас, а не наоборот — этот буткемп для вас!

➡️ Зарегистрироваться на буткемп по ранней цене

📊 Simulative
Please open Telegram to view this post
VIEW IN TELEGRAM
1🔥10😱5👾3💯2🗿2
📥 Гайд по LIMIT и OFFSET

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

показать топ-10 самых дорогих товаров,
вывести последние 20 заказов,
сделать постраничную навигацию в приложении.
вам просто лень писать фильтры, ведь для анализа/оценки хватит n-строк таблицы. НО учтите что будет полное сканирование таблицы!

Для этого в SQL есть два оператора (точнее clauses): LIMIT и OFFSET.

📥 LIMIT — сколько строк выбрать.

LIMIT ограничивает количество строк, которое вернёт запрос.

Пример:
SELECT * 
FROM products
ORDER BY price DESC
LIMIT 5; -- берём только 5 самых дорогих товаров

Что происходит:
ORDER BY price DESC — сортируем товары по убыванию цены.
LIMIT 5 — берём только первые 5 строк после сортировки.

📥 Советы:
Без ORDER BY LIMIT вернёт произвольные строки — на больших таблицах результат может быть сомнительным.
LIMIT экономит ресурсы: не нужно считывать все данные, когда вам нужны только несколько строк.

📥 OFFSET — с какой строки начать.

OFFSET пропускает указанное количество строк перед выборкой.

Пример:
SELECT * 
FROM products
ORDER BY price DESC
LIMIT 5 OFFSET 5; -- берём строки с 6 по 10

Что происходит:
Сортируем товары по цене (ORDER BY price DESC).
Пропускаем первые 5 строк (OFFSET 5).
Берём следующие 5 строк (LIMIT 5).

🪙 Практическое применение: пагинация

LIMIT + OFFSET идеально подходят для страниц сайта или приложения (бэк UI), но можно юзать и при подготовке отчетности, если ложиться в условия ее формирования.
-- Страница 1
SELECT * FROM orders ORDER BY order_date DESC LIMIT 20 OFFSET 0;

-- Страница 2
SELECT * FROM orders ORDER BY order_date DESC LIMIT 20 OFFSET 20;

-- Страница 3
SELECT * FROM orders ORDER BY order_date DESC LIMIT 20 OFFSET 40;

Каждый раз вы берёте новую порцию данных без лишней нагрузки на базу.

🪙 Стоит упомянуть:

Случайные строки с LIMIT.
Чтобы взять случайные строки из таблицы:
SELECT * 
FROM users
ORDER BY RANDOM() -- в разных СУБД отличается
LIMIT 5;

LIMIT в подзапросах.
Можно использовать LIMIT для выборки топ-N в подзапросах:
SELECT *
FROM users
WHERE id IN (
SELECT id
FROM users
ORDER BY created_at DESC
LIMIT 10
);

Всегда используйте ORDER BY с LIMIT. Иначе “первые N” строки могут быть случайными.

🪙 Итог

LIMIT n — Берёт первые n строк
OFFSET m — Пропускает первые m строк
LIMIT n OFFSET m — Берёт n строк, пропустив первые m

Запомните: LIMIT — сколько строк грузить, OFFSET — с какой строки грузить.

#SQL #LIMIT #OFFSET

📱 Подписаться на канал
💻 Курс автора по SQL DDL
🌎 Мой ИТ-стартап
Please open Telegram to view this post
VIEW IN TELEGRAM
1🔥157👾5
Forwarded from Simulative
Узнайте, почему ваши SQL-запросы тормозят 🤖

Медленные SQL-запросы могут стоить бизнесу миллионов: отчёты считаются часами, решения принимаются с задержкой, а ошибки в данных подрывают доверие к аналитике.

На вебинаре Владимир Лунев, бизнес- и системный аналитик с 5-летним опытом работы в ритейле и IT, разберёт 7 реальных кейсов оптимизации SQL-запросов, которые помогали бизнесу принимать быстрые и точные решения.

В ходе вебинара разберём:
🟠 Как понять, что запрос тормозит, и чем это грозит бизнесу;
🟠 Как читать план выполнения (EXPLAIN, EXPLAIN ANALYZE) и находить ошибки;
🟠 Типовые причины медленных запросов и как их исправлять;
🟠 7 реальных кейсов из практики: «было → стало» с разбором кода.

❗️ Встречаемся 24 сентября в 19:00 МСК.

🧡 Обязательно ждём вас в лайве — вы сможете напрямую задать свои вопросы Владимиру Луневу и получить ценный опыт оптимизации SQL-запросов!


➡️ Зарегистрироваться на вебинар

📊 Simulative
Please open Telegram to view this post
VIEW IN TELEGRAM
1🔥95💯4🤔2🤣1
❗️ HAVING в SQL

Многие думают, что оператор HAVING — это просто аналог WHERE, но после GROUP BY. Это упрощение, которое может привести к путанице. Давайте разберём настоящую теорию — шаг за шагом.

Здесь нужно понимать, что SQL-запрос выполняется СУБД не в том порядке, в котором он написан человеком. Это критически важно для понимания HAVING.

❗️ Логический порядок с точки зрения исполнения СУБД (упрощённо):
1. FROM — загрузка данных из таблиц(ы)
2. WHERE — фильтрация отдельных строк
3. GROUP BY — разбиение оставшихся строк на группы
4. Вычисление агрегатных функций (COUNT, SUM, AVG и т.д.) для каждой группы
5. HAVING — фильтрация групп на основе результатов агрегации
6. SELECT — формирование выходных колонок (включая алиасы)
7. ORDER BY, LIMIT, и т.д.

⛔️ Именно потому, что агрегаты появляются только на шаге 4, их нельзя использовать в WHERE — на момент выполнения WHERE (шаг 2) групп ещё не существует!

❗️ HAVING — это условие в SQL, которое фильтрует группы строк после того, как они были объединены с помощью GROUP BY.

❗️ Что такое «группа» в реляционной алгебре?

SQL основан на реляционной алгебре. Оператор GROUP BY трансформирует отношение (таблицу) в множество групп, где каждая группа — это подмножество строк с одинаковым значением ключа группировки.

Пример:
GROUP BY department

Cоздаёт столько групп, сколько уникальных значений в колонке department. Каждая такая группа — новая логическая единица, и к ней можно применять агрегатные функции, которые сводят множество строк к одному значению (например, средняя зарплата в отделе).

❗️ Почему WHERE не может работать с агрегатами?

Потому что WHERE работает на уровне кортежей (строк), а не групп. Он отвечает на вопрос: «Оставить ли эту конкретную строку в результирующем наборе до группировки?». Агрегатные функции, напротив, не определены для одной строки — они требуют множества. Например, AVG(salary) для одной строки — это просто salary, но SQL не позволяет так делать в WHERE, чтобы избежать семантической неоднозначности.

❗️ Когда использовать HAVING?
Используй HAVING, когда твоё условие зависит от результата агрегации по группе.

❗️ Примеры:
«Отделы с более чем 10 сотрудниками» — HAVING COUNT(*) > 10
«Категории товаров, где общая выручка < 1000» — HAVING SUM(price * quantity) < 1000
«Пользователи, сделавшие хотя бы 3 заказа» — HAVING COUNT(order_id) >= 3

❗️ Пример в коде:
Найдём отделы, где средняя зарплата больше 70 000.
SELECT department, AVG(salary) AS avg_salary
FROM employees
GROUP BY department
HAVING AVG(salary) > 70000;

Если попытаться написать это через WHERE — получим ошибку:
WHERE AVG(salary) > 70000
-- СУБД заруинила запрос

Потому что на этапе WHERE ещё нет групп, а значит — нет и средней зарплаты по отделу.

❗️ Итого
Используй WHERE, если фильтруешь по конкретным значениям (например, status = 'active').
Используй HAVING, если фильтруешь по результатам агрегации (COUNT(*) > 5, AVG(price) < 100).

#SQL #HAVING

📱 Подписаться на канал
💻 Курс автора по SQL DDL
🌎 Мой ИТ-стартап
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥29💯9👾52🤔1
Если вы задумывались над тем, чем же все-таки занимаются аналитики, рекомендую подписаться на канал Data Brew!

Канал ведет тот самый аналитик, который смог построить карьеру после курсов и сейчас продолжает расти профессионально.

Автор
🤗 помогает в поиске работы
😊пишет о полезных для аналитиков хардах
🎁делится реальными историями с собеседований
🤬 рассказывает о боли аналитиков
😇 скидывает аналитические мемы

Подписывайся на @data_brew
Please open Telegram to view this post
VIEW IN TELEGRAM
2🔥7👾44
🐘 От академического проекта до лидера open-source: история PostgreSQL

Продолжим тему постов про историю SQL и СУБД, ранее мы уже разбирали:

Как создатель MySQL потерял миллиарды
Историю SQL: от лаборатории IBM до ядра современного ИТ

Теперь настало время одной из самых популярных промышленных СУБД — PostgreSQL

❗️ Начало, проект "Ingres"

Всё началось в 1986 году в Калифорнийском университете в Беркли. Группа исследователей под руководством профессора Майкла Стоунабрейкера уже создала реляционную СУБД Ingres — одну из первых в мире. Но им захотелось большего. Они решили пойти дальше реляционной модели и создать объектно-реляционную СУБД, которая поддерживала бы сложные типы данных, наследование и пользовательские функции. Так родился проект Post-Ingres — "после Ingres".

❗️ Рождение open-source

В 1994 году два аспиранта Андреас Энглесберг и Джонсон Ло портировали Postgres на язык C и добавили поддержку SQL. Это стало поворотным моментом. В том же году код был открыт под лицензией BSD и началась эра сообщества. В 1996 году название изменили на PostgreSQL, чтобы подчеркнуть совместимость со стандартом.

PostgreSQL — одна из самых старых open-source СУБД, которая активно развивается без корпоративного владельца. Никакой Oracle, Microsoft или Google за спиной — только сообщество энтузиастов и профессионалов.

❗️ Эволюция версий: от 6.0 до 16+

1996: Выходит PostgreSQL 6.0 — первая официальная версия с SQL.
1997: Появляется поддержка транзакций и многоверсионного контроля параллелизма (MVCC) — технологии, которая сегодня лежит в основе производительности PostgreSQL.
2005: Версия 8.0 — первая нативная сборка для Windows.
2010: Поддержка JSON (ещё до бума NoSQL!).
2012: JSONB — бинарный, индексируемый JSON. Это стало прорывом: PostgreSQL начал конкурировать с документными базами.
2018: Версия 11 — параллельное создание индексов, улучшенная масштабируемость.
2023: PostgreSQL 16 — улучшения в логической репликации, безопасность, производительность аналитических запросов.
2025: Ожидаеться выход версии 18

PostgreSQL поддерживает более 40 расширяемых типов данных, включая географические (PostGIS), полнотекстовый поиск, массивы, диапазоны, UUID, IP-адреса и даже пользовательские типы.

❗️ Почему PostgreSQL так популярен?

Следует SQL-стандартам лучше, чем многие коммерческие СУБД.
Можно добавлять свои типы, функции, операторы, даже языки программирования (PL/Python, PL/Perl и др.).
ACID-совместимость, отказоустойчивость, репликация.
Более 1000 активных контрибьюторов, регулярные релизы раз в год, никакого vendor lock-in.

Компании вроде Apple, Spotify, Reddit, Cisco и IMDb, Магнит, Яндекс, Сбер используют PostgreSQL в продакшене — иногда с тысячами серверов.

🐘 А почему слон?

Идея слона как символа PostgreSQL появилась в 1997 году — её предложил участник сообщества Дэвид Янг, вдохновлённый детективом Агаты Кристи «Слоны умеют помнить».
В апреле 1999 года в Санкт-Петербурге руководитель небольшой дизайн-студии Дмитрий Самерсов инициировал создание логотипа, а дизайнер Екатерина Папчинская нарисовала эскиз — знаменитого "слона в алмазе"
12 апреля 1999 года изображение под названием slonik.gif было выложено на сайт Дмитрия и отправлено в рассылку pgsql-hackers. Название мгновенно прижилось и стало легендой международного сообщества. Позже логотип стилизовался и пришел к современному варианту.

❗️ Будущее

PostgreSQL продолжает развиваться:
Улучшение работы с AI/ML (через расширения вроде MADlib),
Поддержка векторных встраиваний (для поиска по схожести — актуально для LLM!),
Ещё более мощная логическая репликация,
Оптимизация для облачных и распределённых сред.

❗️ В заключение

Постгре это не просто база данных — это живая легенда с более чем 35-летней историей, открытая для всех и созданная благодаря уму, упорству и страсти к качеству.
И всё это — благодаря университетскому проекту 1980-х, который отказался умирать.

#SQL

📱 Подписаться на канал
💻 Курс автора по SQL DDL
🌎 Мой ИТ-стартап
Please open Telegram to view this post
VIEW IN TELEGRAM
2🔥1610🤯3👾2
💡 Реляционная модель, это не просто таблицы. Это договор между людьми

Когда я только начал работать аналитиком, я думал, что база данных это просто место, где хранятся цифры. Потом я потратил два дня на отчёт, который оказался неверным, потому что не знал: поле status в таблице orders может быть NULL, если заказ ещё не обработан системой.

Но документации по этому поводу не было и узнал я об этом потом только со слов коллег. С тех пор я понял - реляционная модель это не про данные. Это про доверие.

❗️ Таблицы — это интерфейс

В IT мы привыкли к API: чёткие контракты, типы, документация.

Реляционная схема — API для данных.
Имена таблиц и колонок — часть договора.
Типы данных (DATE, BOOLEAN, NUMERIC(10,2)) — гарантии формата.
Ограничения (NOT NULL, FOREIGN KEY, CHECK) — правила игры.

Например, если в колонке user_id есть NULL, значит, система допускает анонимные действия. Это бизнес-решение, зафиксированное в схеме (надеюсь).

❗️ Кто участвует в этом договоре?

Разработчики — создают и меняют схему.
Аналитики — читают данные, строят гипотезы, пишут требования.
ML\BI-инженеры — строят витрины и дашборды, обучают модели.
Менеджеры продукта — принимают решения на основе этих данных.

Если договор нарушен (например, внезапно появляются дубли без первичного ключа), все теряют доверие к данным.

❗️ Что ломает договор?

Колонки вроде data_json со "всем подряд" - нет контракта, только хаос.
Отсутствие документации: "Что значит status = 5?"
Изменение типа колонки без уведомления команд юзающих данные (например, INT стал TEXT).
Использование общих таблиц вроде temp_analytics_2025 как совокупного источника истины.

Это как менять API без версионирования - клиенты падают, но никто не знает почему.

❗️ Договор требует ответственности от всех сторон

Разработчик не должен "временно" писать мусор в notes-поле вместо создания новой сущности.
Аналитик не должен строить отчёт на основе недокументированного поля, даже если "оно работает"
Команда должна иметь владельца данных - человека, который следит за целостностью контракта.

❗️ Как укреплять договор?

Именуйте осознанно: order_created_at, а не date1.
Используйте ограничения: если поле не может быть пустым - NOT NULL.
Документируйте семантику: через комментарии в БД (COMMENT ON COLUMN ...) или Data Dictionary. Если вы бизнес/системный аналитик, подробно описывайте поля и логику, например в конфлюенс.
Согласовывайте изменения: даже переименование колонки событие для всей команды.
Уточняйте и уведомляйте: лучше лишний раз переспросить перед внесением изменений в данные и после уведомить заинтересованных, чем потом отвечать на кучу вопросов "а почему теперь так?"

❗️ Данные, это социальный артефакт

Реляционная модель, не техническая деталь. Это язык согласия между людьми, которые хотят говорить об одном и том же, не путаясь.
Хорошая схема это когда новый аналитик через неделю понимает бизнес, просто читая документацию по модели данных БД.

Посмотрите на любую таблицу в вашей БД. Спросите себя:

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

Если да - вы знаете, с чего начать укреплять договор.

И напоследок анекдот:
Новичок приходит в команду и спрашивает:
— Где почитать про модель данных БД?
— Вся документация в голове у Артёма — отвечает тимлид.
— А как с ним связаться?
— А… он уволился полгода назад.


📱 Подписаться на канал
💻 Курс автора по SQL DDL
🌎 Мой ИТ-стартап
Please open Telegram to view this post
VIEW IN TELEGRAM
2🔥165💯4
0️⃣ NULL в SQL - не "ничего", а "неизвестно"

Когда вы видите NULL в таблице, интуиция подсказывает: "Это просто пусто. Ничего нет. Поле не заполнено".
Но реляционная модель намеренно отказывается от такого упрощения. Вместо "ничего" она вводит состояние неопределённости: значение существует, но нам о нём ничего не известно. Именно поэтому NULL - это не данные, а метаинформация о недостатке данных.

И эта тонкость ломает привычную булеву логику, заставляя SQL работать с трёхзначной логикой (3VL):

TRUE - утверждение верно,
FALSE - утверждение ложно,
UNKNOWN - мы не можем судить

0️⃣ Почему age = NULL ничего не возвращает?

Рассмотрим запрос:
SELECT name FROM employees WHERE age = NULL;

Логика кажется простой: "выведи всех, у кого возраст не указан"

Но СУБД думает иначе. Выражение вида age = NULL не возвращает ни TRUE, ни FALSE.
Поскольку NULL обозначает отсутствие известного значения, сравнение любого выражения с NULL с использованием стандартных операторов (=, <>, <, >, и т.д.) всегда приводит к логическому значению UNKNOWN.

Согласно семантике WHERE, в результирующий набор включаются только те строки, для которых условие оценивается как TRUE. Значения FALSE и UNKNOWN в этом контексте ведут себя одинаково - соответствующие строки исключаются из вывода.

Следовательно, конструкция из примера никогда не возвращает строк, даже если в столбце age присутствуют значения NULL.

Правильный синтаксис - специальный оператор:
SELECT name FROM employees WHERE age IS NULL; -- также антипод IS NOT NULL

Здесь вы не сравниваете значения, а запрашиваете состояние. Эти предикаты предназначены именно для работы с состоянием неопределённости и возвращают строго TRUE или FALSE.

0️⃣ Поведение агрегатных функций

Большинство агрегатов (SUM, AVG, MAX, MIN) игнорируют NULL. Это не ошибка, это следствие семантики "неизвестно":
Если зарплата неизвестна, её нельзя включать в среднее - это исказит реальность.
Если дата рождения неизвестна, нельзя сказать, кто самый старший.

Пример:
Таблица salaries:
id | amount
1 | 5000
2 | NULL
3 | 7000

Запрос:
SELECT AVG(amount) FROM salaries;  -- Результат: 6000 (а не 4000!)

Если вы сознательно хотите трактовать NULL как 0 (например, "не заплатили - значит, ноль"), используйте COALESCE или CASE:
SELECT AVG(COALESCE(amount, 0)) FROM salaries;  -- Теперь: 4000

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

0️⃣ NULL в JOIN, GROUP BY и ORDER BY

JOIN. Строка с NULL в ключе не совпадёт ни с чем - даже с другой NULL. Потому что NULL = NULL - UNKNOWN, а не TRUE.
GROUP BY. Все NULL в одном столбце группируются в одну группу. Это практичное исключение - иначе агрегация была бы бесполезной.
ORDER BY. NULL обычно идут в начале (ASC) или в конце (DESC), но это зависит от СУБД. В PostgreSQL можно управлять:
ORDER BY column NULLS LAST


0️⃣ Практические рекомендации

Никогда не используйте = NULL - только IS NULL / IS NOT NULL.
Явно обрабатывайте NULL в расчётах, если семантика требует замены (через COALESCE, CASE, NULLIF).
Избегайте NOT IN, если подзапрос может вернуть NULL - это классическая ловушка: если в t2. id есть хотя бы один NULL, весь результат будет пустым! Лучше NOT EXISTS или LEFT JOIN ... WHERE t2. id IS NULL.
При проектировании таблицы задайте вопрос: "Это поле может быть неизвестным - или просто необязательным?". Иногда лучше использовать отдельный флаг (is_age_estimated BOOLEAN).

#SQL #NULL

📱 Подписаться на канал
💻 Курс автора по SQL DDL
🌎 Мой ИТ-стартап
Please open Telegram to view this post
VIEW IN TELEGRAM
8🔥219👾4💯2🌚1