🐘 Чем на самом деле занимаются администраторы баз данных (DBA).
Про DBA часто думают так:
«Ну… это человек, который следит, чтобы база не упала».
И да — это правда.
Но это лишь процентов 10 от того, чем DBA занимается на самом деле.
Разберёмся 👇
🔧 1. DBA отвечают за надёжность данных
⚡️ 2. DBA борются за производительность
🔐 3. DBA отвечают за безопасность
🚑 4. DBA — первые, кого будят ночью
🧠 5. DBA — это про системное мышление
🏁 Итог
Про DBA часто думают так:
«Ну… это человек, который следит, чтобы база не упала».
И да — это правда.
Но это лишь процентов 10 от того, чем DBA занимается на самом деле.
Разберёмся 👇
🔧 1. DBA отвечают за надёжность данных
Для бизнеса данные — это деньги, клиенты и история.
DBA делают всё, чтобы:
- данные не пропали
- данные не повредились
- данные можно было восстановить
Бэкапы, репликации, тесты восстановления — их ежедневная рутина.
⚡️ 2. DBA борются за производительность
Если запросы вдруг стали «тормозить»,
скорее всего, DBA уже это заметил.
Они:
- анализируют планы выполнения
- ищут узкие места
- настраивают индексы
- оптимизируют конфигурацию БД
И делают так, чтобы система выдерживала рост нагрузки.
🔐 3. DBA отвечают за безопасность
Кто имеет доступ к данным?
Кто может читать, кто — изменять, а кто — только смотреть?
DBA настраивают:
- роли и права
- доступы
- защиту от случайных и неслучайных ошибок
Чтобы данные не «утекали» и не ломались.
🚑 4. DBA — первые, кого будят ночью
Если база «легла» в 3 часа ночи —
DBA узнаёт об этом первым.
Он:
- ищет причину
- поднимает систему
- минимизирует потери
- делает выводы, чтобы это не повторилось
Спокойствие продакшена — их заслуга.
🧠 5. DBA — это про системное мышление
Хороший DBA понимает не только базу данных, но и:
- как работает приложение
- как идут запросы
- как растёт нагрузка
- где может возникнуть проблема
Они думают на несколько шагов вперёд.
🏁 Итог
DBA — это не просто «админ базы».
Это инженер, который делает так, чтобы бизнес мог спокойно работать, масштабироваться и не бояться за свои данные.
Если база работает стабильно и быстро —
скорее всего, где-то рядом есть хороший DBA.
👍2
UNION, EXCEPT, INTERSECT — операции объединения множеств в SQL.В SQL есть мощный инструмент, про который знают не все,
но который сильно упрощает запросы — операции над множествами.
Если коротко:
они позволяют объединять и сравнивать результаты запросов.
Разберёмся 👇
------------------------------------------------------------------
🔹 UNION — объединить результаты
UNION объединяет результаты двух запросов и убирает дубликаты.
SELECT user_id FROM users_2024
UNION
SELECT user_id FROM users_2025;
Получим всех уникальных пользователей за два года.
Если дубликаты нужны — используйте UNION ALL.
------------------------------------------------------------------
🔹 INTERSECT — найти общее
INTERSECT возвращает только те строки,
которые есть в обоих результатах.
SELECT user_id FROM paid_users
INTERSECT
SELECT user_id FROM active_users;
Пользователи, которые и платят, и активны.
------------------------------------------------------------------
🔹 EXCEPT — найти разницу
EXCEPT показывает строки,
которые есть в первом запросе, но отсутствуют во втором.
SELECT user_id FROM users
EXCEPT
SELECT user_id FROM banned_users;
Все пользователи, кроме заблокированных.
------------------------------------------------------------------
⚠️ Важно помнить
Чтобы операции работали корректно, необходимо:
- одинаковое количество колонок
- одинаковые типы данных
- одинаковый порядок колонок
И да — порядок запросов в EXCEPT имеет значение.
Когда это реально полезно:
- сравнение сегментов
- анализ изменений
- поиск пересечений аудиторий
- очистка данных
- сложная аналитика без лишних JOIN’ов
🔥2
История о том, как LEFT JOIN превратился в INNER JOIN, но никто этого не заметил.
Был у меня запрос. Красивый, аккуратный, должен был выводить все заказы, даже те, которые НЕ в статусе 'paid'.
Смотрю — LEFT JOIN.
Думаю: ну всё правильно, хотим же заказы, даже если оплаты нет.
Запрос работает. Данные возвращает. Прод живёт.
Проходит время.
Приходит вопрос:
— А почему у нас пропали заказы без оплаты? У нас что все заказы только оплаченные?
Я открываю запрос, смотрю ещё раз.
LEFT JOIN — есть.
Вроде всё логично.
А потом PostgreSQL тихо так подсказывает:
— Друг, ты уверен, что это LEFT JOIN?
Я отвечаю:
— Уверен, написано же LEFT JOIN !!
Он продолжает:
— У тебя в запросе условие WHERE p.status = 'paid' —
это не фильтр таблицы orders.
Это фильтр результата после JOIN.
— И для строк, где оплаты нет,
p.status равен NULL.
— А NULL = 'paid' — это не TRUE.
Это ничего. Поэтому я просто выкидываю эти строки.
В этот момент LEFT JOIN:
— Я вообще-то был левым…
А WHERE отвечает:
— Был. Теперь ты INNER.
Исправление оказалось простым,
Был у меня запрос. Красивый, аккуратный, должен был выводить все заказы, даже те, которые НЕ в статусе 'paid'.
SELECT *
FROM orders o
LEFT JOIN payments p ON p.order_id = o.id
WHERE p.status = 'paid';
Смотрю — LEFT JOIN.
Думаю: ну всё правильно, хотим же заказы, даже если оплаты нет.
Запрос работает. Данные возвращает. Прод живёт.
Проходит время.
Приходит вопрос:
— А почему у нас пропали заказы без оплаты? У нас что все заказы только оплаченные?
Я открываю запрос, смотрю ещё раз.
LEFT JOIN — есть.
Вроде всё логично.
А потом PostgreSQL тихо так подсказывает:
— Друг, ты уверен, что это LEFT JOIN?
Я отвечаю:
— Уверен, написано же LEFT JOIN !!
Он продолжает:
— У тебя в запросе условие WHERE p.status = 'paid' —
это не фильтр таблицы orders.
Это фильтр результата после JOIN.
— И для строк, где оплаты нет,
p.status равен NULL.
— А NULL = 'paid' — это не TRUE.
Это ничего. Поэтому я просто выкидываю эти строки.
В этот момент LEFT JOIN:
— Я вообще-то был левым…
А WHERE отвечает:
— Был. Теперь ты INNER.
Исправление оказалось простым,
условие нужно было перенести в LEFT JOIN:SELECT *
FROM orders o
LEFT JOIN payments p ON p.order_id = o.id AND p.status = 'paid';
Вывод:
LEFT JOIN — не гарантия того, что строки сохранятся.
Одно условие в WHERE — и вы сами превращаете его в INNER JOIN.
PostgreSQL не ошибается.
Он просто выполняет то, что вы написали.
Даже если вы написали это «логично».
😁3👍2
🎄 Друзья, вот и подходит к концу 2025 год.
Предлагаю оставить в нём всё лишнее:
ошибки, сомнения, неудачные запросы.
А всё нужное и ценное — опыт, знания, идеи и желание развиваться —
смело забираем с собой в 2026 год.
Уверен, впереди нас ждёт год интересный, технологичный и полный новых открытий.
Пусть будет больше удачных решений, роста, уверенности в себе
и, конечно, достижения всех поставленных целей.
Мотивации, энергии и времени на то, что действительно важно.
И не забываем продолжать качаться и обучаться —
в наше время это уже не цель, а верный спутник на всю жизнь.
С наступающим Новым 2026 годом! 🚀
Пусть он будет сильным, продуктивным и по-настоящему вашим.
Предлагаю оставить в нём всё лишнее:
ошибки, сомнения, неудачные запросы.
А всё нужное и ценное — опыт, знания, идеи и желание развиваться —
смело забираем с собой в 2026 год.
Уверен, впереди нас ждёт год интересный, технологичный и полный новых открытий.
Пусть будет больше удачных решений, роста, уверенности в себе
и, конечно, достижения всех поставленных целей.
Мотивации, энергии и времени на то, что действительно важно.
И не забываем продолжать качаться и обучаться —
в наше время это уже не цель, а верный спутник на всю жизнь.
С наступающим Новым 2026 годом! 🚀
Пусть он будет сильным, продуктивным и по-настоящему вашим.
❤5🔥1
Мы часто слышим, что искусственный интеллект отнимет у людей работу, сделает профессии ненужными и вытеснит человека из привычного мира. Этот страх понятен, но если убрать эмоции и посмотреть на происходящее честно, становится видно: ИИ не уничтожает людей, он убирает всё нечеловеческое.
ИИ не является разумом в человеческом смысле. У него нет желаний, целей, намерений, понимания смысла или ответственности за последствия. Он не думает и не выбирает — он анализирует прошлое, находит закономерности и делает прогнозы. Любое «решение» ИИ — это не выбор, а статистическое предположение, основанное на исторических данных и совпадениях похожих ситуаций. Он всегда смотрит назад, даже когда кажется, что он смотрит в будущее.
Именно поэтому ИИ так хорошо справляется с рутиной, шаблонами, инструкциями и повторяющимися задачами. Он отлично воспроизводит то, что уже было, и масштабирует опыт прошлого. Но он не понимает, когда мир меняется, правила ломаются, а контекст становится новым.
Исчезают не профессии, исчезают роли-исполнители. Если работа человека сводится к выполнению формализованных действий по инструкции, эту инструкцию рано или поздно можно автоматизировать. ИИ не увольняет людей — он просто показывает, где человек давно перестал быть человеком и стал функцией.
Парадокс нашего времени в том, что чем умнее становятся машины, тем важнее становится человек. Но не как набор навыков или источник ручного труда, а как носитель смысла и ответственности. ИИ может предложить тысячу вариантов, построенных на прошлом опыте, но выбрать правильный в новой, неопределённой ситуации всё ещё должен человек.
Мы долго верили, что решающим фактором являются только хард-скиллы, а всё остальное — вторично. ИИ разрушил этот миф. Сегодня настоящей ценностью становятся умение мыслить, видеть контекст, задавать правильные вопросы, договариваться, чувствовать людей и брать на себя ответственность там, где нет готовых данных и нет правильного ответа в истории.
Самая большая опасность заключается не в том, что ИИ станет разумным, а в том, что люди начнут передавать решения системам, которые умеют только прогнозировать, но не понимать ценности. Опасен не искусственный интеллект, а желание снять с себя ответственность и спрятаться за алгоритмом.
Будут ли потери и болезненные изменения? Да. Профессии будут меняться, привычные роли исчезать, а многим придётся переучиваться. Но выиграют не самые умные и не самые технически подкованные, а самые гибкие — те, кто умеет учиться, мыслить и общаться.
ИИ не делает человека ненужным. Он делает ненужным всё то, что в человеке было не-человеческим. И, возможно, впервые за долгое время нам придётся вернуться к тому, что всегда отличало нас от машин: мышлению, ответственности и способности быть живыми.
ИИ не является разумом в человеческом смысле. У него нет желаний, целей, намерений, понимания смысла или ответственности за последствия. Он не думает и не выбирает — он анализирует прошлое, находит закономерности и делает прогнозы. Любое «решение» ИИ — это не выбор, а статистическое предположение, основанное на исторических данных и совпадениях похожих ситуаций. Он всегда смотрит назад, даже когда кажется, что он смотрит в будущее.
Именно поэтому ИИ так хорошо справляется с рутиной, шаблонами, инструкциями и повторяющимися задачами. Он отлично воспроизводит то, что уже было, и масштабирует опыт прошлого. Но он не понимает, когда мир меняется, правила ломаются, а контекст становится новым.
Исчезают не профессии, исчезают роли-исполнители. Если работа человека сводится к выполнению формализованных действий по инструкции, эту инструкцию рано или поздно можно автоматизировать. ИИ не увольняет людей — он просто показывает, где человек давно перестал быть человеком и стал функцией.
Парадокс нашего времени в том, что чем умнее становятся машины, тем важнее становится человек. Но не как набор навыков или источник ручного труда, а как носитель смысла и ответственности. ИИ может предложить тысячу вариантов, построенных на прошлом опыте, но выбрать правильный в новой, неопределённой ситуации всё ещё должен человек.
Мы долго верили, что решающим фактором являются только хард-скиллы, а всё остальное — вторично. ИИ разрушил этот миф. Сегодня настоящей ценностью становятся умение мыслить, видеть контекст, задавать правильные вопросы, договариваться, чувствовать людей и брать на себя ответственность там, где нет готовых данных и нет правильного ответа в истории.
Самая большая опасность заключается не в том, что ИИ станет разумным, а в том, что люди начнут передавать решения системам, которые умеют только прогнозировать, но не понимать ценности. Опасен не искусственный интеллект, а желание снять с себя ответственность и спрятаться за алгоритмом.
Будут ли потери и болезненные изменения? Да. Профессии будут меняться, привычные роли исчезать, а многим придётся переучиваться. Но выиграют не самые умные и не самые технически подкованные, а самые гибкие — те, кто умеет учиться, мыслить и общаться.
ИИ не делает человека ненужным. Он делает ненужным всё то, что в человеке было не-человеческим. И, возможно, впервые за долгое время нам придётся вернуться к тому, что всегда отличало нас от машин: мышлению, ответственности и способности быть живыми.
🔥4👍2
Ребята, всем привет 👋
Наконец-то добрался до запуска — сайт с SQL-тренажёрами и тестами по PostgreSQL вышел в продакшн 🚀
Сейчас на платформе:
- базовый SQL-тренажёр
- продвинутый SQL-тренажёр
- несколько тестов по SQL и PostgreSQL
Сейчас это всё бесплатно, нужно только зарегистрироваться на сайте.
Если вам интересно потренироваться в решении SQL-задач или проверить свои знания — буду рад, если заглянете и попробуете тренажёры.
🔹 Внутри каждого тренажёра есть встроенный форум прямо на сайте — можно обсуждать решения, помогать друг другу и разбирать сложные моменты по ходу обучения.
Также есть отдельная группа в ТГ:
- ветки для каждого продукта
- общая ветка
- обратная связь
Буду очень благодарен за любые отзывы: баги, ошибки, пожелания, идеи и комментарии — всё это можно писать в соответствующих ветках группы в ТГ. Это действительно поможет сделать платформу лучше.
Платформа будет дальше развиваться и расширяться — в планах вырастить её в полноценную, увлекательную образовательную платформу не только по SQL.
В ветках по продуктам можно обсуждать конкретные задания, подходы к решениям и ситуации, когда что-то не получается.
Спасибо всем, кто поддержит 🙏
Ссылка на сайт: https://smartgatepro.ru/
Ссылка на группу сайта в ТГ: t.me/smartgate_pro
Наконец-то добрался до запуска — сайт с SQL-тренажёрами и тестами по PostgreSQL вышел в продакшн 🚀
Сейчас на платформе:
- базовый SQL-тренажёр
- продвинутый SQL-тренажёр
- несколько тестов по SQL и PostgreSQL
Сейчас это всё бесплатно, нужно только зарегистрироваться на сайте.
Если вам интересно потренироваться в решении SQL-задач или проверить свои знания — буду рад, если заглянете и попробуете тренажёры.
🔹 Внутри каждого тренажёра есть встроенный форум прямо на сайте — можно обсуждать решения, помогать друг другу и разбирать сложные моменты по ходу обучения.
Также есть отдельная группа в ТГ:
- ветки для каждого продукта
- общая ветка
- обратная связь
Буду очень благодарен за любые отзывы: баги, ошибки, пожелания, идеи и комментарии — всё это можно писать в соответствующих ветках группы в ТГ. Это действительно поможет сделать платформу лучше.
Платформа будет дальше развиваться и расширяться — в планах вырастить её в полноценную, увлекательную образовательную платформу не только по SQL.
В ветках по продуктам можно обсуждать конкретные задания, подходы к решениям и ситуации, когда что-то не получается.
Спасибо всем, кто поддержит 🙏
Ссылка на сайт: https://smartgatepro.ru/
Ссылка на группу сайта в ТГ: t.me/smartgate_pro
🔥12👏1😁1
Нужно вывести все заказы, кроме оплаченных.
Запрос выглядит предельно логично:
В голове всё быстро:
— paid не нужен → выкидываем Alice и Evan
— shipped, cancelled, returned — подходят
— NULL? Ну, вроде бы тоже не paid
Итого: 5 строк.
Запрос выполняется.
PostgreSQL возвращает… 3 строки.
Без Diana.
Без Frank.
Два заказа просто исчезли.
В этот момент PostgreSQL спокойно уточняет:
Потому что для PostgreSQL:
NULL != 'paid'
— это не TRUE
— и не FALSE
— это UNKNOWN
А в WHERE проходят только строки, где условие TRUE.
NULL не «не равно».
Он просто неизвестен.
И WHERE отвечает:
Вывод неприятный, но полезный:
!= не означает «всё, кроме этого значения».
С NULL это правило ломается.
PostgreSQL не теряет строки.
Он просто выполняет запрос буквально.
Даже если в голове всё выглядело очевидно.
Запрос выглядит предельно логично:
SELECT *
FROM orders
WHERE status != 'paid';
В голове всё быстро:
— paid не нужен → выкидываем Alice и Evan
— shipped, cancelled, returned — подходят
— NULL? Ну, вроде бы тоже не paid
В уме получается:
Bob ✔️
Charlie ✔️
Diana ✔️
Frank ✔️
Grace ✔️
Итого: 5 строк.
Запрос выполняется.
PostgreSQL возвращает… 3 строки.
Без Diana.
Без Frank.
Два заказа просто исчезли.
В этот момент PostgreSQL спокойно уточняет:
— А ты уверен, что NULL != 'paid' — это TRUE?
Потому что для PostgreSQL:
NULL != 'paid'
— это не TRUE
— и не FALSE
— это UNKNOWN
А в WHERE проходят только строки, где условие TRUE.
NULL не «не равно».
Он просто неизвестен.
И WHERE отвечает:
— Не уверен? Значит, эти строки не берём в результат.
Вывод неприятный, но полезный:
!= не означает «всё, кроме этого значения».
С NULL это правило ломается.
PostgreSQL не теряет строки.
Он просто выполняет запрос буквально.
Даже если в голове всё выглядело очевидно.
👍4
Частая ошибка мышления 👇
«Если запрос работает — значит он хороший»
Запрос может быть:
– синтаксически правильным
– логически верным
– возвращать нужный результат
И при этом быть плохим.
Почему? В общих чертах.
🔹 Он делает больше работы, чем нужно
Запрос может сначала собрать «лишнее», а потом отбросить.
Результат тот же, а усилий — больше.
🔹 Он неудобен для базы данных
Некоторые формулировки выглядят логично для человека,
но неудобны для PostgreSQL.
База не «понимает смысл» — она выполняет шаги.
🔹 Он плохо читается
Если запрос сложно понять с первого раза,
его сложно поддерживать, менять и оптимизировать.
А значит, проблемы — вопрос времени.
🔹 Он хорошо работает только сейчас
На небольших таблицах разницы почти не видно.
Но при росте данных такой запрос начинает резко «дорожать».
Главная мысль простая:
👉 Правильный результат ещё не делает запрос хорошим
Хороший запрос — это не только что он вернул,
но и насколько аккуратно он это сделал:
– без лишней работы
– понятно для человека
– спокойно при росте данных
И именно здесь начинается взрослая работа с SQL на уровне мышления.
«Если запрос работает — значит он хороший»
Запрос может быть:
– синтаксически правильным
– логически верным
– возвращать нужный результат
И при этом быть плохим.
Почему? В общих чертах.
🔹 Он делает больше работы, чем нужно
Запрос может сначала собрать «лишнее», а потом отбросить.
Результат тот же, а усилий — больше.
🔹 Он неудобен для базы данных
Некоторые формулировки выглядят логично для человека,
но неудобны для PostgreSQL.
База не «понимает смысл» — она выполняет шаги.
🔹 Он плохо читается
Если запрос сложно понять с первого раза,
его сложно поддерживать, менять и оптимизировать.
А значит, проблемы — вопрос времени.
🔹 Он хорошо работает только сейчас
На небольших таблицах разницы почти не видно.
Но при росте данных такой запрос начинает резко «дорожать».
Главная мысль простая:
👉 Правильный результат ещё не делает запрос хорошим
Хороший запрос — это не только что он вернул,
но и насколько аккуратно он это сделал:
– без лишней работы
– понятно для человека
– спокойно при росте данных
И именно здесь начинается взрослая работа с SQL на уровне мышления.
👍4
Очень часто в SQL проблемы начинаются ещё до первого SELECT.
С формулировки задания. С того, что человек либо не дочитал её до конца, либо понял «примерно» («ну, вроде понятно, сейчас напишу»).
Сначала нужно чётко ответить себе на простой вопрос: что именно от меня хотят получить в результате?
Не какие таблицы, не какие JOIN’ы или другие инструменты я буду применять — а какой смысл у ответа. Пока этого понимания нет, любой SQL будет стрельбой вслепую.
После этого имеет смысл открывать схему БД.
Смотреть, какие таблицы есть, за что каждая отвечает, что на самом деле лежит в столбцах и какие данные нужны для решения задачи.
В этот момент половина запроса уже готова — ты не придумываешь решение, ты его находишь.
И даже когда запрос отработал, работа не закончена.
Нужно вернуться к заданию, перечитать его и сравнить с результатом:
Он точно отвечает на вопрос?
Совпадает ли смысл данных, а не просто количество строк.
SQL — это не про скорость набора.
Это про умение сначала подумать, а потом проверить, что ты решил именно ту задачу, которую просили.
С формулировки задания. С того, что человек либо не дочитал её до конца, либо понял «примерно» («ну, вроде понятно, сейчас напишу»).
Сначала нужно чётко ответить себе на простой вопрос: что именно от меня хотят получить в результате?
Не какие таблицы, не какие JOIN’ы или другие инструменты я буду применять — а какой смысл у ответа. Пока этого понимания нет, любой SQL будет стрельбой вслепую.
После этого имеет смысл открывать схему БД.
Смотреть, какие таблицы есть, за что каждая отвечает, что на самом деле лежит в столбцах и какие данные нужны для решения задачи.
В этот момент половина запроса уже готова — ты не придумываешь решение, ты его находишь.
И даже когда запрос отработал, работа не закончена.
Нужно вернуться к заданию, перечитать его и сравнить с результатом:
Он точно отвечает на вопрос?
Совпадает ли смысл данных, а не просто количество строк.
SQL — это не про скорость набора.
Это про умение сначала подумать, а потом проверить, что ты решил именно ту задачу, которую просили.
👍6
SELECT *
FROM orders o
LEFT JOIN order_details od ON o.order_id = od.order_id;
FROM orders o
LEFT JOIN order_details od ON o.order_id = od.order_id;
Anonymous Quiz
53%
3
41%
4
6%
5
0%
6
❤3
Всем привет. Разберем вчерашнюю викторину про
Ключевая идея:
Разбираем по каждому заказу:
✅ Заказ order_id = 1
В
Это значит:
1 заказ × 2 совпадения = 2 строки в результате
✅ Заказ order_id = 2
В
Значит:
1 заказ × 1 совпадение = 1 строка
✅ Заказ order_id = 3
В
Но это
1 заказ без совпадений = 1 строка с
Итого по математике:
Для
Для
Для
LEFT JOIN.Ключевая идея:
JOIN умножает строкиLEFT JOIN делает так:Берёт каждую строку из левой таблицы (orders) — все заказы сохраняются в результате при любых условиях.
Для каждого заказа ищет все подходящие строки в правой таблице (order_details).
Если подходящих строк несколько — заказ “размножается”: будет столько строк результата, сколько совпадений найдено.
Если совпадений нет — всё равно будет 1 строка, но поля из правой таблицы будут NULL.
Разбираем по каждому заказу:
✅ Заказ order_id = 1
В
order_details есть две строки с order_id = 1.Это значит:
1 заказ × 2 совпадения = 2 строки в результате
✅ Заказ order_id = 2
В
order_details есть одна строка с order_id = 2.Значит:
1 заказ × 1 совпадение = 1 строка
✅ Заказ order_id = 3
В
order_details нет строк с order_id = 3.Но это
LEFT JOIN, поэтому заказ не пропадёт:1 заказ без совпадений = 1 строка с
NULL справаИтого по математике:
Для
order_id = 1 → 2 строкиДля
order_id = 2 → 1 строкаДля
order_id = 3 → 1 строка2 + 1 + 1 = 4 строки ✅
👍2❤1
Начал замечать одну вещь.
Когда ИИ отвечает слишком уверенно,
я начинаю перепроверять.
Когда отвечает неуверенно,
я начинаю перепроверять.
Когда пишет:
«Я могу ошибаться, но…»
— я точно иду перепроверять.
В итоге ИИ стал самым полезным инструментом для развития навыка критического мышления.
Раньше ты сомневался в себе.
Теперь — в ответе модели.
Прогресс ? Прогресс.
И если честно, это хороший знак.
Значит, мы всё ещё думаем головой, а не просто копируем результат.
Хороших выходных 👌
И да — перепроверяйте. Всегда.
("Даже этот пост.")
Когда ИИ отвечает слишком уверенно,
я начинаю перепроверять.
Когда отвечает неуверенно,
я начинаю перепроверять.
Когда пишет:
«Я могу ошибаться, но…»
— я точно иду перепроверять.
В итоге ИИ стал самым полезным инструментом для развития навыка критического мышления.
Раньше ты сомневался в себе.
Теперь — в ответе модели.
Прогресс ? Прогресс.
И если честно, это хороший знак.
Значит, мы всё ещё думаем головой, а не просто копируем результат.
Хороших выходных 👌
И да — перепроверяйте. Всегда.
("Даже этот пост.")
👍9👏1😁1
Зачем в PostgreSQL делать резервные копии?
Иногда кажется, что резервные копии — это что-то из разряда
«на всякий случай» и «потом настроим».
До первого раза.
PostgreSQL — надёжная система.
Но резервные копии делают не потому что PostgreSQL плох,
а потому что мир вокруг него — неидеален.
1️⃣ Человек ошибается (и это нормально)
Самая частая причина потери данных — человеческий фактор.
- DELETE без WHERE
- UPDATE без условия
- TRUNCATE, DROP
- «Я просто хотел проверить»
- «А можно откатить?»
PostgreSQL честно выполняет команды.
Он не понимает, что это была ошибка.
Резервная копия — это возможность вернуться назад, а не разбираться с последствиями.
2️⃣ Техника ломается без предупреждения
Диски выходят из строя.
Файловые системы повреждаются.
Виртуальные машины могут быть утеряны.
("Обычно ночью. В пятницу.")
Если данных нет в резервной копии — их больше не существует.
3️⃣ Данные могут быть испорчены незаметно
Иногда данные не удаляются, а портятся:
- некорректная логика приложения
- ошибки в расчётах
- неверные массовые обновления
- неправильное отключение питания, падения сервера во время записи
Проблема может обнаружиться не сразу.
И вот здесь важно иметь бэкап за нужную дату, а не только «вчерашний».
Какие бывают типы резервного копирования в PostgreSQL?
🔹 Логическое резервное копирование
Инструменты:
- pg_dump
- pg_dumpall
Что это:
- сохраняется структура и данные в виде SQL или архивов
- можно восстановить отдельные таблицы или базы (настраивается)
Плюсы:
- гибкость
- удобно переносить данные
- легко работать в большинстве случаев
Минусы:
- медленнее
- не подходит для очень больших баз
🔹 Физическое резервное копирование
Инструменты:
- pg_basebackup
- копирование каталога данных
Что это:
- снимается копия всех файлов базы данных
- восстанавливается всё целиком (весь кластер)
Плюсы:
- быстро
- подходит для больших объёмов данных
Минусы:
- нельзя восстановить отдельную таблицу
- жёстко привязано к версии PostgreSQL
----------------------------------------------------------------------------------------
Важная мысль напоследок.
Резервное копирование — это не паранойя.
Это базовая гигиена работы с данными.
PostgreSQL делает всё, чтобы данные хранились корректно.
А задача человека — сделать так, чтобы они не пропали навсегда.
("Лучший бэкап — тот, который уже есть и который проверяли.")
Иногда кажется, что резервные копии — это что-то из разряда
«на всякий случай» и «потом настроим».
До первого раза.
PostgreSQL — надёжная система.
Но резервные копии делают не потому что PostgreSQL плох,
а потому что мир вокруг него — неидеален.
1️⃣ Человек ошибается (и это нормально)
Самая частая причина потери данных — человеческий фактор.
- DELETE без WHERE
- UPDATE без условия
- TRUNCATE, DROP
- «Я просто хотел проверить»
- «А можно откатить?»
PostgreSQL честно выполняет команды.
Он не понимает, что это была ошибка.
Резервная копия — это возможность вернуться назад, а не разбираться с последствиями.
2️⃣ Техника ломается без предупреждения
Диски выходят из строя.
Файловые системы повреждаются.
Виртуальные машины могут быть утеряны.
("Обычно ночью. В пятницу.")
Если данных нет в резервной копии — их больше не существует.
3️⃣ Данные могут быть испорчены незаметно
Иногда данные не удаляются, а портятся:
- некорректная логика приложения
- ошибки в расчётах
- неверные массовые обновления
- неправильное отключение питания, падения сервера во время записи
Проблема может обнаружиться не сразу.
И вот здесь важно иметь бэкап за нужную дату, а не только «вчерашний».
Какие бывают типы резервного копирования в PostgreSQL?
🔹 Логическое резервное копирование
Инструменты:
- pg_dump
- pg_dumpall
Что это:
- сохраняется структура и данные в виде SQL или архивов
- можно восстановить отдельные таблицы или базы (настраивается)
Плюсы:
- гибкость
- удобно переносить данные
- легко работать в большинстве случаев
Минусы:
- медленнее
- не подходит для очень больших баз
🔹 Физическое резервное копирование
Инструменты:
- pg_basebackup
- копирование каталога данных
Что это:
- снимается копия всех файлов базы данных
- восстанавливается всё целиком (весь кластер)
Плюсы:
- быстро
- подходит для больших объёмов данных
Минусы:
- нельзя восстановить отдельную таблицу
- жёстко привязано к версии PostgreSQL
----------------------------------------------------------------------------------------
Важная мысль напоследок.
Резервное копирование — это не паранойя.
Это базовая гигиена работы с данными.
PostgreSQL делает всё, чтобы данные хранились корректно.
А задача человека — сделать так, чтобы они не пропали навсегда.
("Лучший бэкап — тот, который уже есть и который проверяли.")
👍3🔥1
Я очень часто слышу от учеников одну и ту же фразу:
«Я вроде выучил синтаксис SQL…
но когда попадается задача — просто ступор.
И я не понимаю, что делать дальше».
И это абсолютно нормально.
Синтаксис — это алфавит.
Ты выучил буквы.
Но это ещё не значит, что ты умеешь читать.
Понимание SQL запросов появляется не из теории.
Оно появляется из практики.
Не из одной задачи. И даже не из десяти.
Нужно:
— решить 100 задач
— потом ещё 100
— потом ещё 100
И в какой-то момент происходит интересная вещь:
ты перестаёшь думать «а какой тут оператор?»
и начинаешь думать «какие данные мне нужны и как их связать».
SQL запросы начинают складываться автоматически.
Без паники.
Без ступора.
Это не талант.
Это не «особое мышление».
Это просто набитая рука, насмотренность и конечно же логическое мышление.
Так что если сейчас тяжело — ты не застрял.
Ты как раз в процессе обучения.
("Другого пути здесь, к сожалению или к счастью, не существует.")
Практика. Практика. Практика.
И всё обязательно встанет на свои места.
«Я вроде выучил синтаксис SQL…
но когда попадается задача — просто ступор.
И я не понимаю, что делать дальше».
И это абсолютно нормально.
Синтаксис — это алфавит.
Ты выучил буквы.
Но это ещё не значит, что ты умеешь читать.
Понимание SQL запросов появляется не из теории.
Оно появляется из практики.
Не из одной задачи. И даже не из десяти.
Нужно:
— решить 100 задач
— потом ещё 100
— потом ещё 100
И в какой-то момент происходит интересная вещь:
ты перестаёшь думать «а какой тут оператор?»
и начинаешь думать «какие данные мне нужны и как их связать».
SQL запросы начинают складываться автоматически.
Без паники.
Без ступора.
Это не талант.
Это не «особое мышление».
Это просто набитая рука, насмотренность и конечно же логическое мышление.
Так что если сейчас тяжело — ты не застрял.
Ты как раз в процессе обучения.
("Другого пути здесь, к сожалению или к счастью, не существует.")
Практика. Практика. Практика.
И всё обязательно встанет на свои места.
👍6🤔2❤1
📌 Что такое CTE в PostgreSQL?
CTE — это Common Table Expression.
На русском — общее табличное выражение.
Проще говоря: это временная таблица, которую ты создаёшь прямо внутри запроса — и потом используешь, как обычную таблицу.
📚 ✅ Когда CTE используют?
⦁ Когда запрос становится слишком сложным и трудно читается.
⦁ Когда один и тот же подзапрос используется несколько раз.
⦁ Когда хочется разбить логику на шаги — как в программе.
⦁ Когда нужно сначала отфильтровать, потом сгруппировать, потом отсортировать — и всё это понятно.
📚 🔧 Как это работает?
1. Пишешь
2. Потом пишешь основной
3. PostgreSQL вычисляет CTE один раз и использует результат дальше.
4. CTE существует только в рамках этого запроса — после него исчезает.
📌 Простой пример: Сколько заказов сделал каждый клиент?
Представим таблицу
Хочешь узнать: кто сделал больше всего заказов?
🔖 🔍 Что тут происходит?
1.
2.
3. Результат:
📚 ✅ Итог:
CTE — это Common Table Expression.
На русском — общее табличное выражение.
Проще говоря: это временная таблица, которую ты создаёшь прямо внутри запроса — и потом используешь, как обычную таблицу.
📚 ✅ Когда CTE используют?
⦁ Когда запрос становится слишком сложным и трудно читается.
⦁ Когда один и тот же подзапрос используется несколько раз.
⦁ Когда хочется разбить логику на шаги — как в программе.
⦁ Когда нужно сначала отфильтровать, потом сгруппировать, потом отсортировать — и всё это понятно.
📚 🔧 Как это работает?
1. Пишешь
WITH имя_таблицы AS (...) — и внутри скобок — обычный SELECT.2. Потом пишешь основной
SELECT, который использует это имя как таблицу.3. PostgreSQL вычисляет CTE один раз и использует результат дальше.
4. CTE существует только в рамках этого запроса — после него исчезает.
📌 Простой пример: Сколько заказов сделал каждый клиент?
Представим таблицу
orders:| id | client_id | amount |
| --- | --------- | ------ |
| 1 | 101 | 500 |
| 2 | 102 | 300 |
| 3 | 101 | 200 |
| 4 | 103 | 800 |
Хочешь узнать: кто сделал больше всего заказов?
WITH client_orders AS (
SELECT client_id, COUNT(*) as order_count
FROM orders
GROUP BY client_id
)
SELECT client_id, order_count
FROM client_orders
WHERE order_count > 1
ORDER BY order_count DESC;
🔖 🔍 Что тут происходит?
1.
WITH client_orders AS (...) — создаём временную таблицу с количеством заказов по каждому клиенту.2.
SELECT ... FROM client_orders — выбираем только тех, у кого больше 1 заказа.3. Результат:
| client_id | order_count |
| --------- | ----------- |
| 101 | 2 |
✅ Всё разбито на логические шаги.
✅ Нет вложенности.
✅ Легко изменить: например, заменить > 1 на > 2 — и всё работает.
📚 ✅ Итог:
CTE — это твой SQL-рефакторинг.
Пишите так, чтобы через месяц вы сами поняли, что делали.
🔥2
🔧 Многие ребята, когда начинают изучать SQL и базы данных, сталкиваются с одной большой проблемой.
Вроде бы:
— SQL-запросы пишем
— данные откуда-то появляются
— SELECT что-то возвращает
— работает же
Но что именно происходит под капотом и как всё это функционирует в рамках целой системы — непонятно.
Отсюда и вопросы:
— куда я вообще пишу SQL?
— откуда берутся данные?
— зачем здесь база данных?
Давайте разберёмся спокойно и по-человечески.
🗄 Что такое база данных на самом деле
База данных — это место, где хранятся данные.
Не магия. Не абстракция.
А по факту — файлы на диске сервера, в которых хранятся данные таблиц (говорим именно про реляционные БД).
Но напрямую работать с этими файлами нельзя.
("Иначе был бы полный хаос.")
⚙️ Зачем нужна СУБД
Между нами и этими файлами всегда стоит СУБД — система управления базами данных (PostgreSQL, MySQL, Oracle и т.д.).
СУБД — это ядро всей системы работы с данными.
Она:
— управляет хранением данных
— следит за целостностью
— обрабатывает SQL-запросы
— находит нужную информацию
Когда ты пишешь SQL, ты не работаешь с файлами напрямую.
Ты формулируешь запрос, а СУБД делает всю техническую работу за тебя.
Примерно как:
— ты не идёшь в архив
— ты говоришь сотруднику: «Принеси мне вот эти документы»
("Архив — это база данных, сотрудник — это СУБД.")
👥 Кто вообще взаимодействует с базой данных
Здесь важно чётко разделить роли, иначе всё быстро путается.
👤 Пользователь сайта или приложения:
Это человек, который:
— заказывает товар
— смотрит список заказов
— нажимает кнопки
Он не знает, что такое SQL. И не должен знать.
Для него существует интерфейс — сайт или приложение.
👨💻 IT-специалист
Это ты:
— аналитик
— разработчик
— инженер
— администратор БД
Ты осознанно работаешь с данными и пишешь SQL руками.
SQL — это твой инструмент управления и анализа данных.
⚙️ Приложение
Приложение — это посредник.
Оно:
— принимает действия пользователя
— формирует SQL-запрос
— отправляет его в СУБД
Но важно понимать:
приложение не “придумывает” SQL само.
Вся логика запросов заложена человеком.
🔄 Как SQL реально попадает в базу данных
SQL-запрос не “лежит” в базе данных.
Он:
— пишется IT-специалистом
— или формируется кодом приложения
— или выполняется через BI-системы
— или вводится вручную в консоли
И всегда передаётся в СУБД извне.
Типовая схема выглядит так:
Пользователь сайта → Приложение → СУБД → База данных
🌐 Как это выглядит на примере сайта
Допустим, пользователь открывает страницу со списком заказов.
Что происходит:
1️⃣ Пользователь нажал кнопку
2️⃣ Сайт отправил запрос на сервер приложения
3️⃣ Сервер сформировал SQL-запрос
4️⃣ Отправил его в СУБД
5️⃣ СУБД нашла данные в базе
6️⃣ Вернула результат приложению
7️⃣ Приложение показало данные пользователю
Пользователь видит данные.
SQL он не видит.
Но без SQL этих данных просто не существовало бы.
🧠 Важная мысль напоследок
SQL — это не просто язык запросов.
Это язык общения между людьми, приложениями и хранилищем данных.
Когда ты понимаешь:
— где физически лежат данные
— кто с ними взаимодействует
— и как SQL проходит весь путь
SQL перестаёт быть «набором команд»
и начинает выглядеть логично и осмысленно.
("А дальше уже действительно становится интересно.")
Вроде бы:
— SQL-запросы пишем
— данные откуда-то появляются
— SELECT что-то возвращает
— работает же
Но что именно происходит под капотом и как всё это функционирует в рамках целой системы — непонятно.
Отсюда и вопросы:
— куда я вообще пишу SQL?
— откуда берутся данные?
— зачем здесь база данных?
Давайте разберёмся спокойно и по-человечески.
🗄 Что такое база данных на самом деле
База данных — это место, где хранятся данные.
Не магия. Не абстракция.
А по факту — файлы на диске сервера, в которых хранятся данные таблиц (говорим именно про реляционные БД).
Но напрямую работать с этими файлами нельзя.
("Иначе был бы полный хаос.")
⚙️ Зачем нужна СУБД
Между нами и этими файлами всегда стоит СУБД — система управления базами данных (PostgreSQL, MySQL, Oracle и т.д.).
СУБД — это ядро всей системы работы с данными.
Она:
— управляет хранением данных
— следит за целостностью
— обрабатывает SQL-запросы
— находит нужную информацию
Когда ты пишешь SQL, ты не работаешь с файлами напрямую.
Ты формулируешь запрос, а СУБД делает всю техническую работу за тебя.
Примерно как:
— ты не идёшь в архив
— ты говоришь сотруднику: «Принеси мне вот эти документы»
("Архив — это база данных, сотрудник — это СУБД.")
👥 Кто вообще взаимодействует с базой данных
Здесь важно чётко разделить роли, иначе всё быстро путается.
👤 Пользователь сайта или приложения:
Это человек, который:
— заказывает товар
— смотрит список заказов
— нажимает кнопки
Он не знает, что такое SQL. И не должен знать.
Для него существует интерфейс — сайт или приложение.
👨💻 IT-специалист
Это ты:
— аналитик
— разработчик
— инженер
— администратор БД
Ты осознанно работаешь с данными и пишешь SQL руками.
SQL — это твой инструмент управления и анализа данных.
⚙️ Приложение
Приложение — это посредник.
Оно:
— принимает действия пользователя
— формирует SQL-запрос
— отправляет его в СУБД
Но важно понимать:
приложение не “придумывает” SQL само.
Вся логика запросов заложена человеком.
🔄 Как SQL реально попадает в базу данных
SQL-запрос не “лежит” в базе данных.
Он:
— пишется IT-специалистом
— или формируется кодом приложения
— или выполняется через BI-системы
— или вводится вручную в консоли
И всегда передаётся в СУБД извне.
Типовая схема выглядит так:
Пользователь сайта → Приложение → СУБД → База данных
🌐 Как это выглядит на примере сайта
Допустим, пользователь открывает страницу со списком заказов.
Что происходит:
1️⃣ Пользователь нажал кнопку
2️⃣ Сайт отправил запрос на сервер приложения
3️⃣ Сервер сформировал SQL-запрос
4️⃣ Отправил его в СУБД
5️⃣ СУБД нашла данные в базе
6️⃣ Вернула результат приложению
7️⃣ Приложение показало данные пользователю
Пользователь видит данные.
SQL он не видит.
Но без SQL этих данных просто не существовало бы.
🧠 Важная мысль напоследок
SQL — это не просто язык запросов.
Это язык общения между людьми, приложениями и хранилищем данных.
Когда ты понимаешь:
— где физически лежат данные
— кто с ними взаимодействует
— и как SQL проходит весь путь
SQL перестаёт быть «набором команд»
и начинает выглядеть логично и осмысленно.
("А дальше уже действительно становится интересно.")
👍3👏3
Что такое индекс в базе данных и как он работает?
Когда таблица в базе данных становится большой, поиск по ней начинает занимать всё больше времени. Если СУБД будет каждый раз просматривать строки одну за другой — это называется полный перебор или последовательное сканирование таблицы (Seq Scan) — производительность быстро просядет. А если нам из всей таблицы нужно выбрать только несколько строк? Становится очевидно, что сканировать все строки таблицы в таком случае не эффективно.
Именно для этого существуют индексы.
📌 Что такое индекс?
Индекс — это отдельная структура данных, которая хранится как самостоятельный файл (так же, как и файл самой таблицы).
Важно понимать:
👉 Индекс — это не часть таблицы внутри её строк.
👉 Это отдельный файл, связанный с таблицей.
По сути, индекс — это упорядоченный список значений одного или нескольких столбцов (по которым строится индекс) + указатели на соответствующие строки таблицы.
Можно представить это как предметный указатель в конце книги, в котором в алфавитном порядке перечислены термины, встречающиеся в книге, и номера страниц, на которых содержится сама информация.
📌 Как устроен индекс?
Чаще всего используется структура B-Tree (сбалансированное дерево).
В индексном файле хранятся:
- значение индексируемого поля
- ссылка (указатель) на строку таблицы
Эта ссылка содержит:
номер блока (страницы) и номер строки внутри блока
📌 Как происходит поиск по индексу?
Разберём пошагово:
1️⃣ Пользователь выполняет запрос:
SELECT * FROM users WHERE email = 'test@mail.com';
2️⃣ СУБД проверяет: есть ли индекс по полю email.
3️⃣ Если индекс есть:
происходит поиск значения 'test@mail.com' в индексном файле (быстро, за счёт специального дерева), далее находится индексная запись
4️⃣ Индексная запись содержит указатель на строку таблицы.
5️⃣ СУБД переходит по этому указателю в файл таблицы и считывает нужную строку.
💡 То есть:
- индекс помогает быстро найти где в таблице лежит нужная строка и указать на эту строку,
- а сами данные читаются уже из файла таблицы.
📌 Почему это быстрее?
Без индекса:
СУБД читает всю таблицу последовательно, то есть все строки, которые в ней есть
С индексом:
СУБД ищет значение в компактной и отсортированной структуре, затем сразу переходит к нужной строке.
В больших таблицах это может ускорить запросы в десятки и сотни раз. Но важно помнить:
Индекс — это:
✔️ ускорение чтения
❗️ но замедление вставки и обновления (индекс тоже нужно обновлять)
❗️ дополнительное место на диске (это отдельный файл)
Если коротко:
Индекс — это отдельный файл с упорядоченными значениями столбца и ссылками на строки таблицы, который позволяет быстро находить нужные данные без полного перебора.
Когда таблица в базе данных становится большой, поиск по ней начинает занимать всё больше времени. Если СУБД будет каждый раз просматривать строки одну за другой — это называется полный перебор или последовательное сканирование таблицы (Seq Scan) — производительность быстро просядет. А если нам из всей таблицы нужно выбрать только несколько строк? Становится очевидно, что сканировать все строки таблицы в таком случае не эффективно.
Именно для этого существуют индексы.
📌 Что такое индекс?
Индекс — это отдельная структура данных, которая хранится как самостоятельный файл (так же, как и файл самой таблицы).
Важно понимать:
👉 Индекс — это не часть таблицы внутри её строк.
👉 Это отдельный файл, связанный с таблицей.
По сути, индекс — это упорядоченный список значений одного или нескольких столбцов (по которым строится индекс) + указатели на соответствующие строки таблицы.
Можно представить это как предметный указатель в конце книги, в котором в алфавитном порядке перечислены термины, встречающиеся в книге, и номера страниц, на которых содержится сама информация.
📌 Как устроен индекс?
Чаще всего используется структура B-Tree (сбалансированное дерево).
В индексном файле хранятся:
- значение индексируемого поля
- ссылка (указатель) на строку таблицы
Эта ссылка содержит:
номер блока (страницы) и номер строки внутри блока
📌 Как происходит поиск по индексу?
Разберём пошагово:
1️⃣ Пользователь выполняет запрос:
SELECT * FROM users WHERE email = 'test@mail.com';
2️⃣ СУБД проверяет: есть ли индекс по полю email.
3️⃣ Если индекс есть:
происходит поиск значения 'test@mail.com' в индексном файле (быстро, за счёт специального дерева), далее находится индексная запись
4️⃣ Индексная запись содержит указатель на строку таблицы.
5️⃣ СУБД переходит по этому указателю в файл таблицы и считывает нужную строку.
💡 То есть:
- индекс помогает быстро найти где в таблице лежит нужная строка и указать на эту строку,
- а сами данные читаются уже из файла таблицы.
📌 Почему это быстрее?
Без индекса:
СУБД читает всю таблицу последовательно, то есть все строки, которые в ней есть
С индексом:
СУБД ищет значение в компактной и отсортированной структуре, затем сразу переходит к нужной строке.
В больших таблицах это может ускорить запросы в десятки и сотни раз. Но важно помнить:
Индекс — это:
✔️ ускорение чтения
❗️ но замедление вставки и обновления (индекс тоже нужно обновлять)
❗️ дополнительное место на диске (это отдельный файл)
Если коротко:
Индекс — это отдельный файл с упорядоченными значениями столбца и ссылками на строки таблицы, который позволяет быстро находить нужные данные без полного перебора.
🔥3👍1
Как я сидел и думал, почему
Писал я как-то простой SQL запрос.
Задача — выбрать заказы за январь.
Логика понятная: берём с 1 по 31 января включительно, ведь мы же знаем, что
Смотрю на результат — заказов за 31 января нет!!!
Написал простой запрос, проверил заказы за '2024-01-31' - заказы то на самом деле есть.
И тут я обнаружил что столбец с заказами кроме даты содержит еще и время, то есть находится в типе данных
В этом и заключалась проблема.
Проблема возникает не в операторе.
Проблема в типе данных.
Если order_date — это timestamp, то:
'2024-01-31' превращается в: 2024-01-31 00:00:00
И фактически диапазон выглядит так:
с 2024-01-01 00:00:00 по 2024-01-31 00:00:00
Всё, что произошло 31 января позже полуночи, уже больше верхней границы.
Как избежать этой ошибки?
1️⃣ Самый правильный способ — полуинтервал
2️⃣ Явно указать конец дня
Можно написать так:
Но:
— можно забыть миллисекунды
— можно столкнуться с разной точностью
— выглядит менее аккуратно
Использовать можно, но это не лучший стиль.
3️⃣ Привести к DATE
Если бизнес-логика действительно про дни, а не про время:
Минус — при приведении типа может не использоваться индекс.
То есть для аналитики нормально.
Для тяжёлых прод-запросов — нужно подумать.
-----------------------------------------------------------------------------------------
ВЫВОД.
Он просто честный.
Он делает ровно то, что написано.
Если тип timestamp, значит учитывается время.
Если граница — полночь, значит всё после неё уже вне диапазона.
SQL не ошибается.
Ошибаемся мы, когда забываем, что данные имеют тип.
И чем раньше начинаешь мыслить типами данных, а не просто «датами», тем меньше странных результатов в отчётах.
Работаем внимательно.
И не забываем смотреть на структуру таблицы перед тем, как писать условия.
BETWEEN вернул странный результат в PostgreSQL.Писал я как-то простой SQL запрос.
Задача — выбрать заказы за январь.
SELECT *
FROM orders
WHERE order_date BETWEEN '2024-01-01' AND '2024-01-31';
Логика понятная: берём с 1 по 31 января включительно, ведь мы же знаем, что
BETWEEN включает в результат нижнюю и верхнюю границу.Смотрю на результат — заказов за 31 января нет!!!
Написал простой запрос, проверил заказы за '2024-01-31' - заказы то на самом деле есть.
И тут я обнаружил что столбец с заказами кроме даты содержит еще и время, то есть находится в типе данных
TIMESTAMP.В этом и заключалась проблема.
BETWEEN работает корректно.BETWEEN — это всегда: >= нижняя граница AND <= верхняя границаПроблема возникает не в операторе.
Проблема в типе данных.
Если order_date — это timestamp, то:
'2024-01-31' превращается в: 2024-01-31 00:00:00
И фактически диапазон выглядит так:
с 2024-01-01 00:00:00 по 2024-01-31 00:00:00
Всё, что произошло 31 января позже полуночи, уже больше верхней границы.
Как избежать этой ошибки?
1️⃣ Самый правильный способ — полуинтервал
WHERE order_date >= '2024-01-01' AND order_date < '2024-02-01';
2️⃣ Явно указать конец дня
Можно написать так:
WHERE order_date BETWEEN '2024-01-01 00:00:00' AND '2024-01-31 23:59:59';
Но:
— можно забыть миллисекунды
— можно столкнуться с разной точностью
— выглядит менее аккуратно
Использовать можно, но это не лучший стиль.
3️⃣ Привести к DATE
Если бизнес-логика действительно про дни, а не про время:
WHERE order_date::date BETWEEN '2024-01-01' AND '2024-01-31';
Минус — при приведении типа может не использоваться индекс.
То есть для аналитики нормально.
Для тяжёлых прод-запросов — нужно подумать.
-----------------------------------------------------------------------------------------
ВЫВОД.
BETWEEN — не плохой оператор.Он просто честный.
Он делает ровно то, что написано.
Если тип timestamp, значит учитывается время.
Если граница — полночь, значит всё после неё уже вне диапазона.
SQL не ошибается.
Ошибаемся мы, когда забываем, что данные имеют тип.
И чем раньше начинаешь мыслить типами данных, а не просто «датами», тем меньше странных результатов в отчётах.
Работаем внимательно.
И не забываем смотреть на структуру таблицы перед тем, как писать условия.
👍3
📌 Задача
Сколько клиентов сделали минимум 2 заказа, и какую долю они составляют от общего количества клиентов. Решаем на SQL.
У нас есть таблица orders со следующей структурой:
order_id — идентификатор заказа
customer_id — идентификатор клиента
order_date — дата заказа
🧠 Как будем мыслить
Шаг 1.
Сначала нужно посчитать, сколько заказов сделал каждый клиент.
Шаг 2.
Понять, у кого заказов ≥ 2.
Шаг 3.
Посчитать:
- общее количество клиентов
- количество клиентов с повторной покупкой
Шаг 4.
Разделить одно на другое и получить долю. Без лишней магии.
🔎 Разбор
1️⃣ CTE (WITH)
Мы создаём "временную таблицу" customer_orders,
где считаем количество заказов на каждого клиента.
2️⃣ FILTER (фишка PostgreSQL)
Конструкция:
- позволяет посчитать только тех клиентов, у которых заказов ≥ 2.
Это аккуратнее и более читаемо, чем писать SUM(CASE WHEN ...).
3️⃣ Делим одно на другое
И приводим к numeric, чтобы избежать целочисленного деления.
Добавляем ROUND(..., 2) — и получаем красивый процент в формате 0.50.
Сам SQL запрос смотри на изображении.
Сколько клиентов сделали минимум 2 заказа, и какую долю они составляют от общего количества клиентов. Решаем на SQL.
У нас есть таблица orders со следующей структурой:
order_id — идентификатор заказа
customer_id — идентификатор клиента
order_date — дата заказа
🧠 Как будем мыслить
Шаг 1.
Сначала нужно посчитать, сколько заказов сделал каждый клиент.
Шаг 2.
Понять, у кого заказов ≥ 2.
Шаг 3.
Посчитать:
- общее количество клиентов
- количество клиентов с повторной покупкой
Шаг 4.
Разделить одно на другое и получить долю. Без лишней магии.
🔎 Разбор
1️⃣ CTE (WITH)
Мы создаём "временную таблицу" customer_orders,
где считаем количество заказов на каждого клиента.
2️⃣ FILTER (фишка PostgreSQL)
Конструкция:
COUNT(*) FILTER (WHERE order_count >= 2)
- позволяет посчитать только тех клиентов, у которых заказов ≥ 2.
Это аккуратнее и более читаемо, чем писать SUM(CASE WHEN ...).
3️⃣ Делим одно на другое
COUNT(*) FILTER (WHERE order_count >= 2) / COUNT(*)
И приводим к numeric, чтобы избежать целочисленного деления.
Добавляем ROUND(..., 2) — и получаем красивый процент в формате 0.50.
Сам SQL запрос смотри на изображении.
🔥2