Веб-версияОткрыть в Telegram
SSQL: Реляционные базы данных

SQL: Реляционные базы данных

@relational_databases · канал · Технологии · в индексе с 2026-07-19
987подписчиков
184средний охват поста
1постов за 30 дней
120постов в индексе
В
Владимир Лунев
Фотография
нажмите — покажем
И смешно и грустно. Но по моему опыту ИИ неплохие результаты показывает, ибо многие аналитики предочитают не думать об оптимизации запросов, ибо целью является, просто получение нужных данных через страдания CPU и прочих механизмов сервера 🖥
3 · 949 ·
В
Владимир Лунев
Фотография
нажмите — покажем
🖥 История SQL: от лаборатории IBM до ядра современного ИТ Привет, сегодня факультативный пост без разборов кода. Все слышали про SQL, многие с ним работали и работают, но давайте разберем откуда он вобще взялся и почему стал так популярен. Это язык, который пережил несколько поворотных технологических эпох в мире ИТ и до сих пор является самым актуальным и популярным инструментом управления данными. 🛠 Рождение: 1970-е ➖ В 1970 году Эдгар Ф. Кодд, исследователь IBM, публикует революционную работу "A Relational Model of Data for Large Shared Data Banks", это была академическая теория, но она перевернула подход к хранению данных. ➖ В 1974-м команда IBM разрабатывает язык SEQUEL (Structured English Query Language) для получения данных из экспериментальной БД System R. ➖ Позже название SEQUEL пришлось сократить до SQL, потому что его уже использовала британская авиакомпания Hawker Siddeley. 💽 Изначально SQL задумывался как язык, понятный и "близкий к английскому", чтобы бизнес-аналитики могли работать с данными без программистов. В реальности — получилось не совсем так. 🛠 Стандартизация и рост ➖ В 1986 году SQL становится стандартом ANSI, а годом позже — ISO. ➖ К началу 90-х SQL — основной язык для большинства СУБД: Oracle, IBM DB2, Microsoft SQL Server, Informix, Sybase. ➖ Возникает "SQL-диалектология": почти каждый вендор внедряет свои особенности (например, LIMIT в MySQL, TOP в SQL Server, FETCH FIRST в стандартном SQL). 💽 Несмотря на принятие стандартов, парадигма "один SQL-запрос для всех СУБД" — остается мифом. Переносимость запроса — один из вечных триггеров боли и страданий разработчиков. 🧊 Реальный мир ➖ С начала 2000-х SQL стал ключевым инструментом для цифровизации банков — внедрение систем управления рисками, скоринга и автоматизации кредитных процессов построено именно на SQL. ➖ В 2000-х годах ритейлеры начали массово внедрять ERP и CRM-системы с поддержкой SQL, что позволило централизовать данные по продажам, складским остаткам и клиентам, улучшая у
5 · 970 ·
В
Владимир Л.
Фотография
нажмите — покажем
👩‍💻 Генерация ключей в SQL: что выбрать — UUID, INT или BIGINT? При проектировании таблиц в реляционных базах данных важно выбрать тип данных для первичного ключа. От него зависят скорость запросов, обеспечение уникальности, масштабируемость и даже архитектура системы. Даже если вы не проектируете БД, понимание ключей поможет в работе с данными. 🖥 Если необходимо, можете прочитать пост про первичный ключ и базовый автоинкримент тут В этом посте рассмотрим три популярных способа генерации первичных ключей: INT, BIGINT и UUID. 🛠 INT — автоинкрементный числовой ключ. Используется по умолчанию в большинстве проектов. Он требует минимум места, обеспечивает быструю сортировку и фильтрацию по индексу, хорошо читается в логах, легко реализуется средствами СУБД. Но у INT есть потолок (2.1 млрд значений) и ограниченная масштабируемость: при распределении на несколько серверов ID могут пересекаться. А ещё ID легко угадываются, что делает структуру базы предсказуемой. ✅ Подходит для централизованных систем с небольшим или средним объёмом данных, занимает минимум места в памяти и индексах, понятен при отладке и в логах. ✅ Быстрота отличная производительность при сортировке и фильтрации по индексу. ✅ Легко реализуется с AUTO_INCREMENT или SERIAL. ❌ ID легко предсказуемы, что может косвенно раскрывать объёмы или порядок операций, также при ошибке планирования в крупных системах может потребоваться переход на BIGINT. ❌ Сложность масштабирования, трудно синхронизировать генерацию ID между несколькими узлами. 🛠 BIGINT — INT с запасом на вырост. То же самое, только 64 бита. Решает проблему переполнения — хватит на миллиарды строк. Сохраняет читаемость, скорость и простоту реализации. Поддерживается всеми современными СУБД. Но индекс и таблицы с такими ключами весят больше. А генерация ID всё ещё централизованная, что не даёт гибкости. ✅ Уместен в крупных монолитных системах с интенсивной вставкой данных (например, финансы, e-commerce). ✅ Сохраняет преимущества INT — скорост
10 · 935 ·
В
Владимир Лунев
Фотография
нажмите — покажем
📥 Что такое CTE (WITH) в SQL? CTE (Common Table Expression) — это временный результирующий набор данных, определённый в WITH-блоке и используемый внутри основного SQL-запроса. Он существует только в рамках одного запроса и не сохраняется в базе. По сути, это "виртуальная подтаблица", которую можно использовать как обычную таблицу, но без создания объекта в БД. Зачем нужен CTE? ➖ Упрощает структуру запроса. Вместо вложенных подзапросов (особенно повторяющихся), можно дать промежуточным результатам имена и вынести их в WITH. ➖ Повышает читаемость. Каждый WITH-блок как отдельный логический шаг, как в пайплайне обработки данных. ➖ Упрощает отладку. Можно легко запускать отдельные WITH-блоки как обычные SELECT-запросы и проверять результаты. ➖ Поддерживает рекурсию. С помощью WITH RECURSIVE можно обходить иерархии, строить деревья и графы. 🪙Общий синтаксис: WITH имя_cte (опциональные_поля) AS ( SQL-запрос ) SELECT ... FROM имя_cte ... WITH объявляет формирование CTE. Можно создавать несколько CTE за один раз, разделяя их запятыми: WITH cte1 AS (...), cte2 AS (...) SELECT ... FROM cte1 JOIN cte2 ... 🪣 Давайте разберем на примере. Задача: Найти всех пользователей, которые заходили в систему за последние 30 дней, и посчитать, сколько заказов сделал каждый из них. 💳 Модель данных: ➖ Таблица пользователи — users (id, name, last_login) Атрибуты: ➖users.id — уникальный идентификатор пользователя, первичный ключ. ➖users.name — имя пользователя, текстовое поле. ➖users.last_login — дата (или дата и время) последнего входа в систему, используется для фильтрации активных пользователей. 🪙Полный состав таблицы users по данным: id name last_login 101 Иван 2025-07-20 105 Ольга 2025-07-15 109 Петр 2025-06-10 ➖ Таблица заказы — orders (id, user_id, created_at). Атрибуты: ➖orders.id — уникальный идентификатор заказа, первичный ключ. ➖orders.user_id — внешний ключ на users .id, связывает заказ с пользователем. ➖orders.created_at — дата (или дата и время)
16 · 1K ·
В
Владимир Лунев
Фотография
нажмите — покажем
🧊 Айсберг SQL Однажды, наткнулся на забавный мем, который с каждым уровнем становится все сложнее и страшнее, посмеялся и забыл. А недавно нашёл статью на Хабр и оказалось, что у мема есть реальное практическое применение, ведь он, по сути, этап за этапом разбирает взаимодействие через SQL с СУБД PostgreSQL, а автор мема SQL-разработчик Джордан Льюис. Так что можно использовать мем, чтобы выстроить свой путь изучения SQL, как методичку)) На этой неделе, кстати, опубликую пост, как быстро погрузиться в SQL, если вы новичок, и за пару недель (или меньше) достичь гордого уровня junior, минимально необходимого для прохождения собеседований.
18 · 1.3K ·
В
Владимир Лунев
Фотография
нажмите — покажем
🪙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) На этой базе строится вся аналитика: подсчёты по клиентам, категориям, регионам и т.д. 📤 Работа с датами и временем Многие зад
80 · 1.7K ·
В
Владимир Лунев
Фотография
нажмите — покажем
Никогда не забывайте про WHERE 😂
7 · 1K ·
В
Владимир Лунев
Фотография
нажмите — покажем
⌛ Основы по работе с датами в 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
15 · 1K ·
В
Владимир Лунев
Фотография
нажмите — покажем
⌛ Основы по работе с датами в 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; -- Считаем разницу между д
10 · 1.2K ·
В
Владимир Лунев
Фотография
нажмите — покажем
👩‍💻 Он создал 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 миллионов евро. Казалось бы — успех! Но: ➖ Монти получил лишь часть от сделки — и упустил шанс стать одним из самых богатых
10 · 1.2K ·
Владимир Лунев
Всем привет)) Совместно @simulative_official организуем буткемп по SQL, регистрация доступна уже сейчас, буду рад вашему участию 👩‍💻
788 ·
В
Фотография
нажмите — покажем
Привет, аналитики! Меня зовут Владимир Лунев. Более 5 лет я работаю в IT как бизнес- и системный аналитик. Я строил процессы и архитектуру реляционных баз данных для аналитиков, чтобы они могли быстро получить качественные данные, а не заниматься ручной обработкой исходной информации. Большую часть карьеры провёл в ритейле, где ежедневно принимаются решения на основе больших потоков данных: продаж, запасов, логистики, прогнозов спроса. Я часто сталкивался с задачами, где точность и скорость обработки данных имели критическое значение: приходилось быстро выявлять скрытые ошибки, обеспечивать корректность бизнес-отчётов и автоматизировать расчёты ключевых показателей. Несколько кейсов из моей работы: 👑 Оптимизировал отчёт и сократил время его выполнения с 3 часов, до 30 минут, не переписывая бизнес-логику, а разобрав EXPLAIN и исправив ошибки SQL-запросов. 👑 Построил систему контроля качества данных на основании проверочных скриптов, которая автоматически ловила дубли, NULL-ловушки и логические противоречия до попадания информации в отчёты. 👑 Разработал автоматизированный процесс агрегации и расчёта KPI для сети магазинов, позволивший ежедневно получать корректные метрики без ошибок. Я буду ведущим SQL-буткемпа — практикума, где вы получите реальные навыки, которые работают в боевых проектах бизнеса. В рамках буткемпа мы разберём: ➖Оптимизацию запросов в SQL — разбор EXPLAIN, выявление «тормозящих» мест, исправление лишних подзапросов и «фантомных» строк для ускорения критичных бизнес-отчётов и выгрузок. ➖Контроль качества данных — научимся писать кастомные скрипты проверок данных для точных и надёжных данных. ➖Прогнозы и тренды — построение когорт, скользящих метрик, lag/lead-анализ и простые линейные прогнозы для точного планирования. ➖Сценарный анализ «что если» — моделирование альтернатив через параметризацию, temp-таблицы и CTE, автоматизация расчётов для оценки влияния изменений на ключевые показатели. ➖ Агрегацию данных и полезные бизнес-метрики — расчёт
4 · 869 ·
В
Владимир Лунев
Фотография
нажмите — покажем
📥 Гайд по 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
6 · 1.4K ·
В
Владимир Л.
Фотография
нажмите — покажем
Узнайте, почему ваши SQL-запросы тормозят 🤖 Медленные SQL-запросы могут стоить бизнесу миллионов: отчёты считаются часами, решения принимаются с задержкой, а ошибки в данных подрывают доверие к аналитике. На вебинаре Владимир Лунев, бизнес- и системный аналитик с 5-летним опытом работы в ритейле и IT, разберёт 7 реальных кейсов оптимизации SQL-запросов, которые помогали бизнесу принимать быстрые и точные решения. В ходе вебинара разберём: 🟠 Как понять, что запрос тормозит, и чем это грозит бизнесу; 🟠 Как читать план выполнения (EXPLAIN, EXPLAIN ANALYZE) и находить ошибки; 🟠 Типовые причины медленных запросов и как их исправлять; 🟠 7 реальных кейсов из практики: «было → стало» с разбором кода. ❗️ Встречаемся 24 сентября в 19:00 МСК. 🧡 Обязательно ждём вас в лайве — вы сможете напрямую задать свои вопросы Владимиру Луневу и получить ценный опыт оптимизации SQL-запросов! ➡️ Зарегистрироваться на вебинар 📊 Simulative
4 · 1.4K ·
В
Владимир Лунев
Опрос
нажмите — покажем
1.3K ·
В
Владимир Лунев
Фотография
нажмите — покажем
❗️ 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, чтобы избежать семантической неоднознач
36 · 1.5K ·
В
Владимир Л.
Если вы задумывались над тем, чем же все-таки занимаются аналитики, рекомендую подписаться на канал Data Brew! Канал ведет тот самый аналитик, который смог построить карьеру после курсов и сейчас продолжает расти профессионально. Автор 🤗 помогает в поиске работы 😊пишет о полезных для аналитиков хардах 🎁делится реальными историями с собеседований 🤬 рассказывает о боли аналитиков 😇 скидывает аналитические мемы Подписывайся на @data_brew
2 · 1.3K ·
В
Владимир Л.
Фотография
нажмите — покажем
🐘 От академического проекта до лидера 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 — улучшения в логической репликации, безопасность, производительность ан
6 · 1.3K ·
В
Владимир Лунев
Фотография
нажмите — покажем
💡 Реляционная модель, это не просто таблицы. Это договор между людьми Когда я только начал работать аналитиком, я думал, что база данных это просто место, где хранятся цифры. Потом я потратил два дня на отчёт, который оказался неверным, потому что не знал: поле 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-поле вместо создания новой сущности. ➖ Аналитик не должен строить отчёт на основе недокументированного поля, даже если "оно работает" ➖ Команда должн
9 · 1.5K ·
В
Владимир Лунев
Фотография
нажмите — покажем
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. Это не ошибка, это следствие семантики "неизвестно": ➖ Если зарплата неизвестна, её нельзя включать в среднее - это исказит реальность. ➖ Если дата рождения неизвестна, нельзя сказать, кто самый старший. При
26 · 1.8K ·
В
Владимир Л.
Фотография
нажмите — покажем
🥳Всех с наступающим! Решил подвести, итоги года для канала. Создавая его в феврале, я даже не думал, что получу такой крутой отклик от вас. Нас уже +1к, чему я безумно рад. 🏆 Хочу поблагодарить каждого подписчика за то, что читаете мой контент, ставите реакции, пишите коменты. Вы лучшие! 🍑Немного статистики: за этот год, было написано 115 постов, получено 1.8к реакций и 78.8к просмотров 🔥Посты с самым большим количеством реакций: ➖ Null в SQL — не "ничего", а неизвестно ➖ Having в SQL ➖ Junior-ready: выучить SQL и пройти собесы. Часть 1/2 🚀 От себя отмечу ещё пару постов: ➖Реляционная модель это не просто таблицы, это договор между людьми. — тут я немного ударился в философию данных, в следующем году планирую это активно продолжать 😂 ➖Он создал MySQL — и потерял миллиарды. История, о которой редко рассказывают — пост нового формата, потом написал ещё несколько таких, как по мне, читать чью-то историю это всегда интересно, ведь за любым ПО всегда стоят люди. ➖SQL Injection: как одна кавычка может взломать базу данных — ну тут все понятно 💻 На самом деле, ещё бы долго продолжал этот список, например, мне нравится серия постов про нормализацию данных или пока еще не полностью законченный обзор по работе с датами и временем Ещё мне забавно, было наблюдать за ростом качества контента, если первые посты были типовыми заметками, то последние стали вполне неплохими практическими рекомендациями или обзорами. В следующем году буду и дальше совершенствоваться в этом. Под конец года, писал довольно мало, из-за высокой нагрузки на работе, прочих проектах, в следующем году обещаю исправится, буду писать пост каждую неделю 😆 В общем, увидимся в 2026! 👍 📱 Подписаться на канал 💻 Курс автора по SQL DDL
6 · 2K ·
V
Vladimir Lejn
Всем привет)) Я вернулся, так что с этой недели будут новые посты, будем воскрешать канал. Пропадал из за загруженности на работе и своих проектах.
1.3K ·
Vladimir Lejn
👩‍💻 Типы данных в PostgreSQL: как они устроены и почему их выбор имеет значение Одна из самых распространенных ошибок при проектировании базы данных это выбирать типы данных по принципу "лишь бы поместилось". На самом деле тип данных определяет не только допустимые значения, но и способ их хранения, объем занимаемой памяти, производительность запросов и размер индексов. PostgreSQL предоставляет широкий набор встроенных типов данных, каждый из которых предназначен для решения определенных задач. В этом посте коротко, постарался описать, основные типы которые встречаются в постгре. Тут кста пост про то как создали постгре 🖥 ❗️ Целочисленные типы Для хранения целых чисел PostgreSQL предоставляет три основных типа: SMALLINT INTEGER BIGINT ➖ SMALLINT занимает 2 байта и хранит значения в диапазоне от -32 768 до 32 767. ➖ INTEGER (или сокращенно INT) занимает 4 байта и является наиболее часто используемым типом. Его диапазон составляет от -2 147 483 648 до 2 147 483 647. ➖ BIGINT занимает 8 байт и используется, когда диапазона INTEGER недостаточно, например для очень больших идентификаторов или счетчиков. Типы SERIAL, BIGSERIAL и SMALLSERIAL не являются отдельными типами данных. Это специальная запись, которая автоматически создает последовательность (SEQUENCE) и задает значение по умолчанию для соответствующего целочисленного столбца. При выборе типа рекомендуется использовать минимально достаточный размер. Это позволяет уменьшить объем хранения данных и размер индексов, хотя в современных системах влияние на производительность обычно менее заметно, чем влияние правильно построенных индексов и структуры запросов. ❗️ Числа с фиксированной точностью Для хранения значений, где важна абсолютная точность, используются типы NUMERIC и DECIMAL. price NUMERIC(10,2) Первый параметр определяет максимальное количество цифр, второй, количество цифр после десятичной точки. Например: 99999999.99 Главное преимущество NUMERIC это возможность хранить десятичные числа с заданно
13 · 844 ·
V
Фотография
нажмите — покажем
Краткий справочник по типам данных к посту
20 · 1K ·
V
Vladimir Lejn
Фотография
нажмите — покажем
❗️ Как найти дубли и оставить последнюю запись Одна из самых частых задач аналитика, это получить одну актуальную (последнюю) запись на каждый объект. Например, в таблице по одному клиенту хранится несколько состояний: создан/проверен/одобрен/заблокирован. Формально client_id повторяется. Но это не обязательно ошибка - таблица может хранить историю изменений (см. пикчу) Давайте, разберем, как выполнить эту задачу (на примере постгре) ❗️ Сначала найдём повторяющиеся ключи SELECT client_id, COUNT(*) AS cnt FROM client_status GROUP BY client_id HAVING COUNT(*) > 1; Такой запрос покажет клиентов, у которых больше одной записи. Он не обязателен, а выполянется скорее для диагностики, чтобы понять у каких client_id вообще есть несколько строк и сколько таких случаев. Но если нам нужно актуальное состояние клиента, просто удалить повторные строки нельзя. Нужно определить, какая запись считается последней. ❗️ Выбираем последнюю запись через ROW_NUMBER() WITH ranked AS ( SELECT client_id, status, updated_at, id, ROW_NUMBER() OVER ( PARTITION BY client_id ORDER BY updated_at DESC, id DESC ) AS rn FROM client_status ) SELECT client_id, status, updated_at FROM ranked WHERE rn = 1; Здесь происходит три вещи. ➖ PARTITION BY client_id - Записи нумеруются отдельно для каждого клиента. ➖ ORDER BY updated_at DESC - Самая свежая запись получает первый номер. ➖ WHERE rn = 1 - В результате остаётся только одна актуальная строка на каждого клиента. ❗️ Зачем нужен дополнительный критерий сортировки У двух записей может совпасть updated_at. Если сортировать только по времени, порядок между такими строками будет неоднозначным. Поэтому нужен дополнительный критерий, который делает выбор стабильным. В примере используется id DESC, но в реальной системе лучше опираться на поле, которое действительно отражает порядок изменений: номер версии, последовательность события или другой бизнес-
9 · 184 ·

Открытая публичная лента из поискового индекса ChatCrawler — «Google по публичному Telegram»; обновляется по мере обхода площадки. Время — UTC.

Только публичный контент, официальный API Telegram. О проекте · Вопросы · Чего мы не делаем · Убрать страницу из выдачи · Каталог · Поиск · Как мы считаем