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

Меня зовут Владимир Лунев (@lejnlune). Интересуюсь архитектурой систем и моделей данных.
Download Telegram
👩‍💻 Он создал 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