Дима SQL-ит 🧑‍💻 (Аналитика данных, AI)
2.1K subscribers
51 photos
18 videos
110 links
👨‍💻 Блог аналитика данных в IT

📩 По менторству и сотрудничеству: @catdem
Download Telegram
🎙 Иду на AHA'26 — и вам советую:

22 мая в Москве проходит AHA'26 — конференция для тех, кто работает с данными и AI. Решил пойти сам — и вот почему.

Там реально интересная программа: как компании проверяют идеи быстрее и дешевле, как строят AI-продукты, которые реально работают, как не утонуть в данных и доверять тому, что в них написано. Без воды — только практика от команд, которые уже это сделали.

Выступают ребята из Яндекса, Авиасейлс, Сбера, X5 Tech, ВкусВилла, Wildberries, Т-Банка и ещё десятков компаний. Это не те, кто рассказывает «как надо» в теории — это те, кто уже запустил и работает с этим каждый день.

Форматы:
• Офлайн — 39 900 ₽ (22 мая + онлайн-день 14 мая + записи на 6 месяцев)
• Онлайн — 19 900 ₽ (трансляции 14 и 22 мая + материалы на 6 месяцев)

🎁 Для подписчиков моего канала — скидка 10% по промокоду DSQLIT10 при регистрации на сайте.

👋 Если тоже идёте офлайн — пишите, возможно, пересечёмся
Планируете идти? Офлайн или онлайн? Делитесь в комментариях!
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥77❤‍🔥43🐳1
⚡️ Параллельные запросы в ClickHouse через Python — ускоряем выгрузку в разы:

Знакомая ситуация: нужно выгрузить данные за 30 дней, пишешь цикл, день за днём, и ждёшь 30 минут.
А можно запустить все запросы одновременно и получить результат в 5–10 раз быстрее.
Сегодня покажу, как это сделать на простом примере.

Что сделаем:
🟢 Напишем функцию, которая выгружает данные за один день из ClickHouse.
🟢 Запустим её для нескольких дат параллельно с помощью ThreadPoolExecutor.
🟢Соберём все результаты в один DataFrame.

Разбор по шагам:

1️⃣ Функция для одного дня:

Создаём функцию load_day — она принимает дату, делает запрос в ClickHouse и возвращает DataFrame:
import clickhouse_connect
import pandas as pd

def load_day(date_str):
print(f' [{date_str}] → запрос начат')
client = clickhouse_connect.get_client(**CH_CREDS)
df = client.query_df(f"""
SELECT * FROM events
WHERE date = '{date_str}'
""")
client.close()
print(f' [{date_str}] → готово, строк: {len(df)}')
return df


2️⃣ Запускаем параллельно:

Используем ThreadPoolExecutor. Ключевой момент — функция начинает выполняться прямо в момент вызова submit():
from concurrent.futures import ThreadPoolExecutor, as_completed

dates = ['2024-01-01', '2024-01-02', '2024-01-03', '2024-01-04']

executor = ThreadPoolExecutor(max_workers=3)
tasks = {executor.submit(load_day, d): d for d in dates}
# ↑ вот здесь load_day УЖЕ запустилась в фоновом потоке
# submit() не ждёт результата — сразу возвращает "квитанцию" (Future)
# и цикл переходит к следующей дате


Что происходит под капотом:
• submit(load_day, '2024-01-01') → поток 1 сразу побежал делать запрос в ClickHouse
• submit(load_day, '2024-01-02') → поток 2 сразу побежал, пока первый ещё работает
• submit(load_day, '2024-01-03') → поток 3 сразу побежал 
• submit(load_day, '2024-01-04') → все 3 воркера заняты — ждёт в очереди

То есть submit() — это как «отдать задание курьеру». Курьер побежал, а ты уже отдаёшь задание следующему. max_workers=3 — значит у тебя 3 курьера. Четвёртое задание ляжет на стол и подождёт, пока кто-то вернётся.

3️⃣ Собираем результаты:

as_completed отдаёт задачи по мере их завершения — какая первая закончилась, ту и получаем:
results = []
for task in as_completed(tasks):
date = tasks[task]
try:
results.append(task.result())
print(f' {date} — результат получен ')
except Exception as e:
print(f' {date} — ошибка: {e} ')

executor.shutdown()
df = pd.concat(results, ignore_index=True)
print(f'Всего строк: {len(df)}')


🌟 Как это выглядит в консоли:

  [2024-01-01] → запрос начат     ← воркер 1 стартовал
[2024-01-02] → запрос начат ← воркер 2 стартовал
[2024-01-03] → запрос начат ← воркер 3 стартовал
[2024-01-03] → готово, строк: 1200
2024-01-03 — результат получен
[2024-01-04] → запрос начат ← воркер 3 освободился, взял 4-й день
[2024-01-01] → готово, строк: 980
2024-01-01 — результат получен
...


Итог: 🤩

Как выбирать max_workers? 
• Для тяжёлых запросов к БД: 3–5 воркеров
• Для лёгких API-запросов: 10–20 воркеров 
• Начинайте с 3 и смотрите на нагрузку базы — ClickHouse может обрабатывать ограниченное число запросов одновременно

🚀 Работает не только с ClickHouse — PostgreSQL, MySQL, любые API. Паттерн универсальный.

🔥 Набираем 70 реакций на этот пост — так я пойму, что стоит делать больше таких разборов.
📤 Пересылай пост коллеге или другу из аналитики — это бесплатно и помогает каналу расти. Спасибо!


🚬 Вопросы, менторство, консультации: Написать в ЛС | mentor.dima-sqlit.ru


@dima_sqlit
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥33❤‍🔥5🐳5
🤯 Аналитика с изнанки: как выглядит работа с данными в B2B:

Сегодня хочу познакомить вас с Олегом — аналитиком данных с 5+ лет в B2B и B2G-проектах. Работал с заказчиками от стартапов до госсектора, набил шишки на каждом этапе — от сбора требований до сдачи отчётов.

Рекомендую начать знакомство с постов:
1) Первый — как Олег попал в IT: от техподдержки охранной компании, через проваленное тестовое — до аналитика на реальных проектах. Мотивирует 🔥
2) Второй — история «Договорился и передоговорился»: заказчик согласовал объём, а потом пришёл с 300% дополнительных требований за те же деньги. 😈
3) Третий — план канала на 2026 год, что Олег будет разбирать весь год и в какой последовательности — от Excel и SQL до Python, портфолио и продуктового мышления. Удобно, чтобы не пропустить что-то нужное 🌟
4) И много других интересных постов......

Если вам интересно:
• как устроена работа аналитика в B2B и B2G
• как выстраивать отношения с заказчиками и защищать свои границы
• как строить карьеру в IT с нуля — без нужного диплома и опыта

Подписывайтесь на «Data Дзен», чтобы не потерять 🤨
Please open Telegram to view this post
VIEW IN TELEGRAM
5321
🤖 Сделал телеграм-бота за вечер — и вот зачем:


Раньше прикладывал материалы прямо в постах или комментариях.
Но когда материала становится больше — это неудобно: и вам лень искать по истории, и мне неудобно хранить.
Поэтому я сделал отдельного бота. Логично, удобно, по-человечески.

Как это работает — win-win для всех: 🤯

1️⃣ Для вас — все материалы собраны в одном месте. Заходите в бот, тыкаете нужное, и оно сразу прилетает вам. Никакой беготни по постам.
2️⃣ Для меня — бот требует подписку на канал, и тем самым помогает мне наращивать аудиторию. Абсолютно бесплатно для вас — это просто подписка.
3️⃣ В будущем — возможно появятся платные материалы. Но пока две модели: совсем без подписки, или с подпиской. Всё прозрачно.

И да — написал этого бота за один вечер при помощи нейронок 🌟
Это к тому, что AI уже сейчас позволяет создавать проекты, которые реально закрывают ваши задачи даже если вы не разработчик. 🌟

Что уже есть в боте: 🤛

Первые 5 каруселей по A/B тестам — уже там. Я давно хотел систематизировать для себя эту тему, и решил совместить полезное с приятным: делаю красивые слайды, которые коротко и понятно объясняют материал по AB-тестам.

Буду рад вашей обратной связи:
• Как работает бот?
• Нравится ли визуал и подача?
• Что непонятно или хочется доработать?
• Накиньте ваших реакций, чтобы понимать интересно вам такое или нет 🔥

А если вы хорошо шарите в A/B тестах и хотите помочь с материалом — вэлком в ЛС

Итог: 🤩

• Если вам самим интересно внедрить AI — в работу, в личные проекты, или просто понять, что с этим вообще можно делать — могу проконсульровать (все индивидуально под ваш запрос).

• Ну или может быть вам нужно сделать какой-то аналогичны проект под ключ, также можете писать с вашими запросами, интересно и в эту тему развиваться.

🌟 Ссылка на бота (гоу тестировать): Бот_канала_dima_sqlit
🚬 Вопросы, менторство, консультации: Написать в ЛС | mentor.dima-sqlit.ru


@dima_sqlit
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥10❤‍🔥7🐳411
👍AHA 2026 - мой первый раз:

Ранее писал про то, как я был первый раз на матемаркетинге, вот здесь можно почитать про это.
Ну а сейчас напишу про мой первый раз на AHA 🤩

С кем удалось пообщаться и познакомиться:
🛒 Ребята с Авито
🥚 Ребята из МТС
💬 Ребята из ВКонтакте
🖼️ Ребята из Т1
🌟 Несколько IT-блогеров

Завёл кучу полезных контактов — это, пожалуй, одна из главных ценностей таких мероприятий.
Некоторые доклады послушаю в записи. Всё-таки доклад можно посмотреть потом, а живое общение — только в моменте. Поэтому ни о чём не жалею.

На фото — всё, что удалось натаскать со стендов. Смотрите сами 😄


Итог: 🤩

Были на AHA 2026? Что смогли забрать со стендов? Пишите в комментариях — может, пересечёмся на следующем мероприятии в Москве!


А пока хочу спросить: что хотите видеть дальше? 
🔧 Техничку — SQL, особенности СУБД, Python
🏠 Материал про IT-ипотеку и ремонт (накопилось много — планирую начать писать про это)
👇Или предложите свою тему в комментах


🌟 Бот с бесплатными материалами от автора канала: Бот_канала_dima_sqlit
🚬 Вопросы, менторство, консультации: Написать в ЛС | mentor.dima-sqlit.ru


@dima_sqlit
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥14❤‍🔥108
❤️ Переменные в SQL: один раз написал — везде обновилось

Вам знакома ситуация, когда - написал большой sql запрос для задачи, а потом заказчик говорит: «Покажи то же самое, но за прошлый квартал» ?
И вы начинаете искать дату по всему файлу. Находите все вхождения, правите — и где-то всё равно пропускаешь одно. Запрос считает не то.
В общем очень много рутины.

🟢 В Python мы бы написали переменную в начале и пере использовали ее везде:
start_date = "2024-01-01"
discount_threshold = 0.10


🟢 Но в SQL тоже можно кое что придумать:
WITH params AS (
SELECT
DATE '2024-01-01' AS period_start,
DATE '2024-03-31' AS period_end,
0.10 AS discount_threshold
),
big_orders AS (
SELECT
o.order_id,
o.amount,
o.discount
FROM orders o
CROSS JOIN params p
WHERE o.order_date BETWEEN p.period_start AND p.period_end
AND o.discount > p.discount_threshold
)
SELECT * FROM big_orders


Все параметры — в одном месте сверху. Поменял квартал один раз — везде пересчиталось.

CROSS JOIN здесь — это не страшно.
params возвращает одну строку.
CROSS JOIN просто «прицепляет» эту строку к каждой строке основной таблицы.

🟢 Хотите еще таких лайфхаков ?
🔥 Набираем 70 реакций на этот пост, чтобы подобные посты выходили чаще

Итог: 🤩

🗂 Это один из тех приёмов, который занимает 10 секунд, но экономит кучу времени на поддержке запроса.
А как вы решаете эту проблему — хардкодите или есть другой подход? Пишите в комментах!
📤 Пересылай пост коллеге или другу из аналитики — это бесплатно и помогает каналу расти. Спасибо!


🚬 Вопросы, обучение, консультации: Написать в ЛС | mentor.dima-sqlit.ru


@dima_sqlit
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥65❤‍🔥1793
🔐 SQL-инъекция — типы, примеры и защита: всё что нужно знать аналитику:

Один из вопросов, который может быть на собесе - это что такое "SQL-инъекция".
Давайте разберёмся, как обычно с кодом и без воды.

🟢 Как работает атака:

Бэкенд строит запрос прямо из того, что ввёл пользователь:
SELECT * FROM users
WHERE username = 'ВВОД' AND password = 'ВВОД';


Кавычки вокруг ввода уже вшиты в шаблон кода. Злоумышленник вводит admin' -- и запрос превращается в:
WHERE username = 'admin' --' AND password = '...';


Левая кавычка уже есть в шаблоне — злоумышленник дописывает только закрывающую '. Она обрывает строку досрочно, -- превращает всё остальное в комментарий. Проверка пароля выброшена — вход открыт.

🟢 3 основных типа SQL-инъекций:

1️⃣ Классическая — результат виден прямо в ответе сайта. Самый простой случай как выше.
2️⃣ Слепая (Blind) — сайт не выводит данные, но страница реагирует по-разному. Злоумышленник добавляет условие через AND к рабочему запросу:
SELECT * FROM products WHERE id = 1
AND SUBSTRING(password, 1, 1) = 'a'

Если буква угадана → TRUE AND TRUE → товар найден → страница загрузилась Если не угадана → TRUE AND FALSE → товар не найден → страница пустая
По реакции страницы злоумышленник понимает верна ли буква — как игра «горячо-холодно». Перебирает символ за символом.
3️⃣ Через UNION — дописывает свой SELECT к оригинальному и вытаскивает данные из любой таблицы. Структуру БД знать заранее не нужно — она вытаскивается через information_schema, системный справочник который есть в каждой БД:
-- Шаг 1: узнать все таблицы
' UNION SELECT table_name, null FROM information_schema.tables --

-- Шаг 2: узнать поля нужной таблицы
' UNION SELECT column_name, null FROM information_schema.columns
WHERE table_name = 'users' --

-- Шаг 3: вытащить данные
' UNION SELECT username, password FROM users --


🟢 Как защититься:

Без защиты Python склеивает строку и отдаёт в БД целиком — данные и команды уже неразличимы:
# ПЛОХО
query = "SELECT * FROM users WHERE username = '" + username + "'"


С параметрами шаблон и данные уходят в БД раздельно:
# ХОРОШО
cursor.execute(
"SELECT * FROM users WHERE username = %s",
(username,)
)


БД сначала получает шаблон → разбирает и фиксирует структуру запроса. Потом получает данные — и воспринимает их только как текст для поиска. Апостроф внутри admin' -- уже просто символ, а не SQL-синтаксис — структура зафиксирована и данные её изменить не могут.

🟢 Ответ на собесе — коротко:

«SQL-инъекция — это вид атаки, когда пользовательский ввод попадает напрямую в строку SQL-запроса и исполняется как код. Защита — параметризованные запросы: шаблон и данные идут в БД раздельно, поэтому данные никогда не интерпретируются как SQL-команды.»


Итог: 🤩


Спрашивали про SQL-инъекцию на вашем собесе? Пишите в комментарии!
✔️ Подпишитесь на канал, чтобы не пропустить следующие посты.

🚬 Вопросы, менторство, консультации: Написать в ЛС | mentor.dima-sqlit.ru


@dima_sqlit
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥19❤‍🔥86🐳111
📊 SQL трюк — как добавить строку «Все категории» к любому отчёту через UNION ALL (ЧАСТЬ 1):

Ситуация, с которой многие сталкиваются на работе.
Давайте представим таблицу с продажами orders:
order_id | category | revenue
1 | Одежда | 1500
2 | Обувь | 1200
3 | Техника | 2500
4 | Одежда | 5500
.........


И нужно сделать отчёт по продажам, который будет показывать в разрезе категорий тотал продажи — и при этом должна быть отдельная категория, которая объединяла бы все остальные. Её как раз мы искусственно и добавим через UNION ALL.

🟢 Шаг 1 — обычная разбивка по категориям:
SELECT
category,
SUM(revenue) AS total_revenue,
COUNT(order_id) AS orders_count
FROM orders
GROUP BY category


Получаем это:
category | total_revenue | orders_count
Одежда | 7000 | 2
Обувь | 1200 | 1
Техника | 2500 | 1

Хорошо, но итога по всем нет. Добавляем его через UNION ALL.

🟢 Шаг 2 — добавляем строку «Все категории»:
SELECT
category,
SUM(revenue) AS total_revenue,
COUNT(order_id) AS orders_count
FROM orders
GROUP BY category

UNION ALL

SELECT
'Все категории' AS category,
SUM(revenue),
COUNT(order_id)
FROM orders


Результат:
category      | total_revenue | orders_count
Одежда | 7000 | 2
Обувь | 1200 | 1
Техника | 2500 | 1
Все категории | 10700 | 4


Второй запрос считает тотал по всей таблице, а в поле category мы просто подставляем строку 'Все категории' — и она встаёт отдельной строкой в результате.

Почему UNION ALL, а не просто UNION?
UNION под капотом делает сортировку и удаляет дубликаты — это лишняя работа для базы.
UNION ALL просто склеивает результаты как есть, без лишних операций.

В нашем случае дублей нет — строка 'Все категории' явно уникальна.
Так что UNION тут ни к чему, берём UNION ALL — он быстрее.

🟢 Бонус — строка с тоталом всегда внизу:
WITH combined AS (
SELECT
category,
SUM(revenue) AS total_revenue,
COUNT(order_id) AS orders_count
FROM orders
GROUP BY category

UNION ALL

SELECT
'Все категории',
SUM(revenue),
COUNT(order_id)
FROM orders
)
SELECT *
FROM combined
ORDER BY
CASE WHEN category = 'Все категории' THEN 1 ELSE 0 END,
category


🟢 Хотите еще таких лайфхаков ?
🔥 Набираем 70 реакций на этот пост, чтобы подобные посты выходили чаще

Итог: 🤩

❤️ Поддержать канал бустами, чтобы у автора появился дополнительный функционал можно - здесь (это бесплатно и доступно с подпиской telegram premium)
А какие ещё задачи решаете через UNION ALL — поделитесь в комментариях!
✔️ Подпишитесь на канал, чтобы не пропустить следующие хаки.


🚬 Вопросы, обучение, консультации: Написать в ЛС | mentor.dima-sqlit.ru


@dima_sqlit
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥41❤‍🔥11🐳10
🏠 IT ипотека (Часть 1) — выбор города и района:

Решил задокументировать весь путь — от выбора места до финального результата. Это первый пост из серии, поехали.

Почему вообще купил и зачем именно сейчас: 
Хотелось закрыть гештальт. Может, это и не самое выгодное финансовое решение, но психологически — точно правильное. Своя квартира = спокойствие (по крайней мере у меня так).

Почему не Москва:
Изначально хотел, конечно, Москву, но эту опцию быстро прикрыли и я не успел, но считаю, что IT ипотека на данный момент все равно один из самых привлекательных вариантов. Ну если не Москва, то ближайшее подмосковье подумал я и начал смотреть варианты, для меня основные параметры были это транспортная доступность и готовые варианты, чтобы быстро сделать ремонт и заехать. В итоге был выбран город Красногорск.

Что по итогу выбрал:
По итогу выбор пал на ЖК, который находится рядом с МЦД (в 10 минутах ходьбы). По отделке — это черновой вариант (стены и окна). White box оставались только трех-комнатные квартиры, что дорого и не ликвидно. Поскольку это черновой вариант решено было проектировать и разбираться во всем этом самостоятельно (благо есть знакомые и родственники с кем можно было советоваться). Подумал, что будет интересно под разобраться в этом (тем более по образованию я инженер-строитель) по этому в следующих постах буду рассказывать про ремонт, создание проекта, где я смог сэкономить и так далее.

🔥 Набираем 70 реакций на этот пост, чтобы посты про IT ипотеку выходили быстрее

Итог: 🤩


А как вы относитесь к Ипотеке?
✔️ Подпишитесь на канал, чтобы не пропустить следующие посты.

🚬 Вопросы, менторство, консультации: Написать в ЛС | mentor.dima-sqlit.ru


@dima_sqlit
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥76❤‍🔥8🐳8
📊 SQL трюк — как добавить строку «Все категории» к любому отчёту через ROLLUP (ЧАСТЬ 2):

В прошлом посте мы добавляли итоговую строку через UNION ALL — это рабочий метод, но есть способ элегантнее.

Знакомьтесь:
GROUP BY ROLLUP — встроенный механизм SQL для автоматических итогов.

🟢 Что такое ROLLUP на пальцах:

ROLLUP — это расширение GROUP BY, которое автоматически добавляет строки с агрегатными итогами. Вместо того чтобы писать второй запрос и клеить через UNION ALL — просто добавляем одно слово

🟢 Шаг 1 — пишем запрос с ROLLUP:

SELECT
category,
SUM(revenue) AS total_revenue,
COUNT(order_id) AS orders_count
FROM orders
GROUP BY ROLLUP(category)


Результат:
category | total_revenue | orders_count
Одежда | 7000 | 2
Обувь | 1200 | 1
Техника | 2500 | 1
NULL | 10700 | 4


Итоговая строка появилась автоматически, но в поле category стоит NULL — это сигнал ROLLUP, что строка является итогом по всей группе.

🟢 Шаг 2 — заменяем NULL на «Все категории»:

Используем COALESCE, чтобы подменить NULL на читаемую метку:
SELECT
COALESCE(category, 'Все категории') AS category,
SUM(revenue) AS total_revenue,
COUNT(order_id) AS orders_count
FROM orders
GROUP BY ROLLUP(category)


Результат:
category      | total_revenue | orders_count
Одежда | 7000 | 2
Обувь | 1200 | 1
Техника | 2500 | 1
Все категории | 10700 | 4


Чисто и лаконично — никакого второго запроса.

🟢 Важный момент — а что если в данных уже есть NULL в category?

Представим, что в таблице есть строки с незаполненной категорией:
order_id | category | revenue
1 | Одежда | 1500
2 | Обувь | 1200
3 | NULL | 800 ← категория не указана
4 | Одежда | 5500


Запускаем запрос с COALESCE — и получаем проблему:
category      | total_revenue | orders_count
Одежда | 7000 | 2
Обувь | 1200 | 1
Все категории | 800 | 1 ← это был NULL из данных!
Все категории | 10700 | 4 ← это реальный итог ROLLUP


COALESCE не различает: это NULL из данных или NULL от ROLLUP — он заменяет оба.

🟢 Решение — используем GROUPING():

Функция GROUPING(column) возвращает 1, если строка итоговая (от ROLLUP), и 0 — если это обычная строка с NULL из данных:
SELECT
CASE
WHEN GROUPING(category) = 1 THEN 'Все категории'
ELSE COALESCE(category, 'Не указана')
END AS category,
SUM(revenue) AS total_revenue,
COUNT(order_id) AS orders_count
FROM orders
GROUP BY ROLLUP(category)
ORDER BY
GROUPING(category),
category


Результат:
category      | total_revenue | orders_count
Не указана | 800 | 1 ← NULL из данных
Одежда | 7000 | 2
Обувь | 1200 | 1
Все категории | 10700 | 4 ← итог ROLLUP


Теперь всё на своих местах.

🟢 Хотите еще таких лайфхаков ?
🔥 Набираем 70 реакций на этот пост, чтобы подобные посты выходили чаще

Итог: 🤩

❤️ Поддержать канал бустами, чтобы у автора появился дополнительный функционал можно - здесь (это бесплатно и доступно с подпиской telegram premium)
А знали про ROLLUP и GROUPING() раньше? Делитесь в комментариях!
✔️ Подпишитесь на канал, чтобы не пропустить следующие хаки.


🚬 Вопросы, обучение, консультации: Написать в ЛС | mentor.dima-sqlit.ru


@dima_sqlit
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥41❤‍🔥2🐳211
🤖 Что такое MCP — как дать нейросети доступ к вашим данным (часть 1):

Если вы уже работаете в Cursor, Claude Code, Codex, LM Studio или другой IDE где есть нейросети — вы наверняка встречали термин MCP. Разберем, что это и зачем нужно.

Что такое MCP? 🎚

MCP (Model Context Protocol) — открытый стандарт, который позволяет ИИ-клиенту подключаться к внешним данным и системам через специальные инструменты — Tools.

Без MCP модель работает только с тем, что ты вставил ей в чат.
Хочешь узнать метрику из своей базы — скопировал данные вручную, вставил, получил ответ.
MCP убирает этот шаг: модель сама идет в твою базу, достает нужное и отвечает.
Вы просто спрашиваете.

Схема простая:
• MCP Клиент — ваша среда (Cursor, Claude Desktop, Codex, LM Studio и другие)
• MCP Сервер — ваш код с инструментами
• Tool — функция, которую модель вызывает сама, когда понимает что она нужна

Скиллы — это же то же самое? 🎚

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

Может показаться, что скилл умеет то же самое, что и mcp и возникает вопрос — зачем нужен mcp?

Можно ведь написать скилл, который запускает bash или Python.
Но вот в чём различия — это не скилл запускает скрипты.
Cursor и другие IDE сами имеют встроенные инструменты: запуск команд, чтение файлов, редактирование кода — они зашиты внутрь приложения, никак не связаны с MCP.

• Скилл — это промпт, который говорит модели «используй вот этот встроенный инструмент вот так».
• MCP — другая история. Вы пишете свой код и подключаете его через протокол. Теперь у модели есть инструмент, который делает ровно то, что вы закодили — без ограничений клиента.

Пишем свой MCP-сервер на Python: 🎚

Библиотека fastmcp делает это просто:
from mcp.server.fastmcp import FastMCP
import sqlite3

mcp = FastMCP("WorkMetrics")

@mcp.tool()
def get_sales_by_region(region: str) -> list:
"""
Возвращает продажи по указанному региону за текущий месяц.
Используй когда пользователь спрашивает о продажах или
выручке по региону.
"""
conn = sqlite3.connect("metrics.db")
cursor = conn.cursor()
cursor.execute(
"SELECT date, revenue FROM sales WHERE region=?", (region,)
)
result = cursor.fetchall()
conn.close()
return result

if __name__ == "__main__":
mcp.run()


Прописываем сервер в mcp.json — и всё.
Пишете в чате: «Покажи продажи по Москве» — модель сама вызывает нужный инструмент.


🟢 Хотите еще про нейронки ?
🔥 Набираем 80 реакций на этот пост, чтобы подобные посты выходили чаще

Итог: 🤩

На посты про MCP меня вдохновило вот это видео — рекомендую к просмотру для большего понимания.

❤️ Поддержать канал бустами, чтобы у автора появился дополнительный функционал можно - здесь (это бесплатно и доступно с подпиской telegram premium)
Уже пробовал MCP если да, то какие? Делись в комментариях!
✔️ Подпишитесь на канал, чтобы не пропустить следующие хаки.


🚬 Вопросы, обучение, консультации: Написать в ЛС | mentor.dima-sqlit.ru


@dima_sqlit
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥37❤‍🔥7🐳511
🏠 IT ипотека (Часть 2) — как я проектировал квартиру (Remplanner, Pinterest, ChatGPT):

Когда берёшь черновую квартиру — впереди не просто ремонт, а целый проект. Надо придумать планировку, расстановку мебели и понять, как это вообще будет выглядеть в натуре. Делюсь своим стеком инструментов которые я использовал.

🎚 Инструмент 1 Remplanner:

Это был мой основной инструмент на этапе планировки квартиры.
Работает прямо в браузере по сути autocad, но с большим количеством готовых инструментов и шаблонов.

Что я делал в Remplanner:
• Прорабатывал разные варианты планировки
• Расставлял мебель и проверял, насколько удобно всё помещается
• Планировал розетки, выключатели и освещение
• Смотрел, как будут выглядеть комнаты в 3D
• Формировал понятные чертежи для строителей

Самое полезное — можно быстро делать несколько вариантов и сравнивать их между собой. На бумаге многие идеи выглядят отлично, а в планировщике сразу становится видно, где не открывается шкаф, не проходит стол или остаётся слишком узкий проход.

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

🎚 Инструмент 2 — Pinterest:

Это этап «насмотренности».
Работает так:
• Вбиваете запрос: например, «квартира 45 кв», «скандинавский стиль серый» — и просто смотришь
• Постепенно понимаешь, что тебе нравится, а что нет
• Сохраняешь понравившееся → вырисовывается общее направление

Повторить всё один в один с Pinterest не получится — дорого или нереализуемо. Но это и не нужно. Важно сформировать своё видение.

🎚 Инструмент 3 — ChatGPT:

Когда стены уже возведены — делаешь фотографию реального пространства и загружаешь в ChatGPT. Дальше:
• «Хочу здесь поставить диван, что посоветуешь?»
• «Как можно оформить этот угол?»
• «Что сюда органично впишется по цвету?»

ChatGPT накидывает варианты прямо под ваш конкретный интерьер (приложил пример, как я подбирал кухню).

🔥 Набираем 70 реакций на этот пост, чтобы посты про IT ипотеку выходили быстрее

Итог: 🤩


Чем пользовались при ремонте или перестановке? Делитесь в комментариях!
✔️ Подпишитесь на канал, чтобы не пропустить следующие посты.

🚬 Вопросы, менторство, консультации: Написать в ЛС | mentor.dima-sqlit.ru


@dima_sqlit
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥37❤‍🔥11🐳8
🤖 Что такое MCP сервер — как научить нейросеть писать SQL под ваши данные (часть 2):

В первой части разобрали что такое MCP и написали первый инструмент. Сегодня идем дальше — что делать, если запросы сложнее и нейросеть не знает как у вас организованы таблицы (их описание и как они могут соединяться между собой).

Проблема: модель не знает ваши таблицы 🎚

Фиксированный тул — например get_sales_by_region — работает хорошо для простых запросов. Но что если пользователь спросит: «Сравни выручку по регионам с прошлым кварталом с разбивкой по сегментам клиентов»?

Тут нужно несколько таблиц, JOIN и оконные функции. Заранее написать тул под каждый такой запрос — нереально (реально, конечно, но не логично мягко говоря).

Решение: дать модели два инструмента — получить схему и возможность выполнить любой запрос.

Как это устроено: 🎚

@mcp.tool()
def get_database_schema(domain: str = "all") -> str:
"""
Возвращает схему БД: таблицы, поля, типы данных и связи.
Вызывай ПЕРЕД тем как писать SQL-запрос.
domain: 'sales', 'customers', 'products' или 'all'
"""
if domain == "all":
files = ["sales.md", "customers.md", "products.md"]
else:
files = [f"{domain}.md"]

result = ""
for f in files:
with open(f"docs/{f}", "r") as file:
result += file.read() + "\n\n"
return result

@mcp.tool()
def execute_sql(query: str) -> list:
"""
Выполняет SELECT-запрос к базе данных.
Используй только после get_database_schema.
Только SELECT — никаких изменений данных.
"""
conn = sqlite3.connect("metrics.db")
cursor = conn.cursor()
cursor.execute(query)
result = cursor.fetchall()
conn.close()
return result


Модель сначала вызывает get_database_schema, читает описание таблиц и связей — потом сама пишет SQL и передает в execute_sql.

Как организовать файлы схемы: 🎚

Файлы лежат рядом с сервером в папке /docs. Внутри — описание таблиц, типы данных и как они связаны:
## Таблица orders
- order_id INT — первичный ключ
- customer_id INT — FK → customers.customer_id
- region VARCHAR — регион продажи
- revenue FLOAT — выручка
- created_at DATE — дата заказа

## Связи
orders.customer_id → customers.customer_id


Прочитав это, модель сама поймет как делать JOIN между таблицами — объяснять ничего не нужно.

Один MCP или несколько? 🎚

Один MCP-сервер = один проект. Не нужно плодить отдельный сервер под каждую таблицу. Все связанные таблицы и тулы живут в одном сервере. Если у вас две независимые системы — например аналитическая база и CRM — вот тогда имеет смысл делать два разных сервера. Здесь нет явного ответа, нужно подходить индивидуально к каждому проекту.

А если схема хранится в Confluence? 🎚

Рабочий вариант — тул делает запрос к Confluence API и достает описание нужной таблицы прямо оттуда:
@mcp.tool()
def get_table_docs(table_name: str) -> str:
"""
Достает описание таблицы из корпоративной документации.
Используй перед написанием SQL если нужны детали схемы.
"""
# запрос к Confluence API
response = requests.get(
f"{CONFLUENCE_URL}/rest/api/content",
params={"title": table_name, "expand": "body.storage"},
auth=(USER, TOKEN)
)
return response.json()["results"][0]["body"]["storage"]["value"]



🟢 Хотите еще про нейронки ?
🔥 Набираем 80 реакций на этот пост, чтобы подобные посты выходили чаще

Итог: 🤩

❤️ Поддержать канал бустами, чтобы у автора появился дополнительный функционал можно - здесь (это бесплатно и доступно с подпиской telegram premium)
Какие идеи для использования MCP есть у вас? Делись в комментариях!
✔️ Подпишитесь на канал, чтобы не пропустить следующие хаки.


🚬 Вопросы, обучение, консультации: Написать в ЛС | mentor.dima-sqlit.ru


@dima_sqlit
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥23❤‍🔥4🐳31
This media is not supported in your browser
VIEW IN TELEGRAM
🗂 Порядок выполнения sql запроса — и почему алиас в WHERE не работает:

Часто вижу одну и ту же ошибку — человек пишет запрос, придумывает алиас в SELECT, а потом пытается использовать его в WHERE или HAVING. И получает ошибку. Почему?

Всё дело в порядке выполнения SQL.
На самом деле SQL выполняется совсем не в том порядке, в котором мы его пишем. Вот реальная последовательность:

1️⃣ FROM — сначала движок идёт к таблицам
2️⃣ JOIN
 — потом движок соединяет таблицы
2️⃣ WHERE — фильтрует строки до группировки
3️⃣ GROUP BY — группирует данные
4️⃣ HAVING — фильтрует уже сгруппированные данные
5️⃣ SELECT — только сейчас вычисляются выражения и алиасы
6️⃣ ORDER BY — сортировка результата
7️⃣ LIMIT — обрезание до нужного числа строк

Пример 1 — классическая ошибка с алиасом:
--  Не работает — алиас revenue ещё не существует на шаге WHERE
SELECT
order_id,
amount * 0.9 AS revenue
FROM orders
WHERE revenue > 1000;

-- Правильно — повторяем выражение напрямую
SELECT
order_id,
amount * 0.9 AS revenue
FROM orders
WHERE amount * 0.9 > 1000;


Пример 2 — почему HAVING, а не WHERE:
--  Нельзя — WHERE выполняется ДО GROUP BY
SELECT
user_id,
COUNT(*) AS order_count
FROM orders
GROUP BY user_id
WHERE order_count > 5;

-- Правильно — HAVING фильтрует после группировки
SELECT
user_id,
COUNT(*) AS order_count
FROM orders
GROUP BY user_id
HAVING COUNT(*) > 5;


Пример 3 — вот почему все пишут CTE:
Иногда хочется сначала что-то посчитать, а потом фильтровать по результату. Именно для этого и придумали CTE — они позволяют «сохранить» промежуточный результат и работать с ним как с таблицей.
--  CTE решает проблему: сначала считаем, потом фильтруем
WITH revenue_calc AS (
SELECT
order_id,
amount * 0.9 AS revenue
FROM orders
)
SELECT *
FROM revenue_calc
WHERE revenue > 1000;


Видите? В CTE SELECT уже выполнился — алиас revenue существует — и теперь во внешнем запросе WHERE отрабатывает по нему без проблем.

Итог: 🤩

❤️ Поддержать канал бустами, чтобы у автора появился дополнительный функционал можно - здесь (это бесплатно и доступно с подпиской telegram premium)
Сталкивались с этой ошибкой? Или, может, объясняете это джунам — как объясняете? Пишите в комментах!
✔️ Подпишитесь на канал, чтобы не пропустить следующие хаки.


🚬 Вопросы, обучение, консультации: Написать в ЛС | mentor.dima-sqlit.ru


@dima_sqlit
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥20❤‍🔥2🐳2
This media is not supported in your browser
VIEW IN TELEGRAM
🏦 Разбор задачи с собеседования в Тинькофф (Т-банк). Задача про светофор сколько минут ты теряешь на красном?

Условие: Каждый день едете на работу. На пути один светофор: 2 минуты горит зелёный, 1 минуту — красный. Сколько времени вы ожидаемо простоите за 100 поездок?

Задачи на матожидание — любимый инструмент интервьюеров у аналитиков и DS. Выглядят как «логика про жизнь», а проверяют умение считать вероятности. Разберём на пальцах.

1️⃣ Находим цикл светофора
Полный цикл = 2 + 1 = 3 минуты. Вы приезжаете к светофору в случайный момент — считаем, что равномерно распределённый по этим 3 минутам.

2️⃣ Считаем вероятности
P(зелёный) = 2/3  →  ждать 0 минут
P(красный) = 1/3 → придётся постоять


3️⃣ Сколько ждать, если попали на красный?
Вот тут сыплются многие. Вы ждёте не всю минуту. Вы приезжаете в случайный момент красной фазы: иногда в самом начале (придется ждать 1 минуту), иногда в конце (придется ждать 0 минут). В среднем — получим:
Среднее ожидание на красном = (1+0)/2 = 0.5 минуты


4️⃣ Собираем матожидание за одну поездку
E = P(зелёный) × 0  +  P(красный) × 0.5
E = (2/3) × 0 + (1/3) × 0.5
E = 1/6 минуты ≈ 10 секунд


5️⃣ Умножаем на 100 поездок
100 × 1/6 ≈ 16.7 минуты = 16 минут 40 секунд


Итог: 🤩  

❤️ Поддержать канал бустами, чтобы у автора появился дополнительный функционал можно - здесь (это бесплатно и доступно с подпиской telegram premium)
  Сколько у вас получилось до того, как дочитали до ответа? Делись в комментариях!
✔️ Подпишитесь на канал, чтобы не пропустить следующие хаки.


🚬 Вопросы, обучение, консультации:  Написать в ЛС | mentor.dima-sqlit.ru 


@dima_sqlit
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥44❤‍🔥12🐳6
Собесы, собесы, собесы…

Если тебе интересны обзоры собеседований и разборы заданий, то можешь заглянуть на канал Айти-Пингвин | Дата инженер. Это канал дата-инженера, который активно делает обзоры пройденных собесов, разбирает задачки и технологии, а также рассказывает о своем карьерном пути.

Что, на мой взгляд, будет полезно для собесов на аналитика?

1. На джуна разбор вопросов по SQL , вопросы про джоины и задача на джоины.

2. На мидла - задачи по SQL + оптимизация SQL-запросов. Будет очень полезно и джунам.

3. Порадовали задачи на адекватность. 😅 Будь готов, что на собесе спросят что-то совсем базовое и простое, но некоторых такие задачи вгоняют в ступор :) С разрешения Пингвина приведу загадки с собеседования.

Вот еще несколько интересных постов:
• Статья по индексам и партициям
• Транзакции и ACID
• Итоги за год
• Удаление дублей в Greenplum
• История о потере данных

Из последнего:
обзоры собесов в сбер (1, 2, GigaData)
• Neoflex
• Обзор большого собеседования с IT_One
• Лига цифровой экономики (проект Альфа банк)
• Популярные вопросы с hr скрининга
• Очередные вопросы по SQL с собеседования


В целом, на канале разнообразный контент. Заходите и изучайте😁

it пингвин | data engineer 🐧
🔥12❤‍🔥7🐳62
This media is not supported in your browser
VIEW IN TELEGRAM
🛒  Разбор задачи с собеседования Магнит OMNI (MAGNIT TECH).
Сколько покупок нужно, чтобы собрать все 10 стикеров?


Условие: В наборе 10 наклеек. На кассе дают одну случайную за любую покупку. сколько покупок нужно, чтобы собрать все 10?

Задача на пониманием и умение считать математическое ожидание. Разберём на пальцах:

1️⃣ Главное правило: переворачиваем дробь
Если вероятность равна p, то среднее количество попыток до первого успеха равно 1/p. Например:
Вероятность 1/10 → 10/1 = 10 попыток
Вероятность 5/10 → 10/5 = 2 попыток


2️⃣
Шанс поймать новую наклейку
Собираем по этапам. Чем больше наклеек в альбоме, тем реже попадается новая:
этап 1:  собрано 0  →  шанс новой 10/10
этап 2: собрано 1 → шанс новой 9/10
...
этап 10: собрано 9 → шанс новой 1/10


3️⃣
Собираем матожидание и считаем ответ
Переворачиваем шанс каждого этапа в число покупок и складываем всё:
этап 1 (запишем общую формулу):
E = 10/10 + 10/9 + 10/8 + ... + 10/2 + 10/1

этап 2 (вынесем общий множитель за скобки):
E = 10 × (1 + 1/2 + 1/3 + ... + 1/10

этап 3 (считаем ответ):
E = 10 × 2.93 ≈ 29 покупок

Почти половина из этих них уходит на последние 2-3 наклейки.

Итог:
 🤩  

❤️ Поддержать канал бустами, чтобы у автора появился дополнительный функционал можно - здесь (это бесплатно и доступно с подпиской telegram premium)
  Сколько у вас получилось до того, как дочитали до ответа? Делись в комментариях!
✔️ Подпишитесь на канал, чтобы не пропустить следующие хаки.


🚬 Вопросы, обучение, консультации:  Написать в ЛС | mentor.dima-sqlit.ru 


@dima_sqlit
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥24❤‍🔥53
This media is not supported in your browser
VIEW IN TELEGRAM
📊 DAU, WAU, MAU и sticky factor — метрики активности:

Пришло время разбираться с метриками, начнем с DAU, WAU, MAU и sticky factor 😘

1️⃣ Что это
DAU — уникальные пользователи за день
WAU — за 7 дней
MAU — за 30 дней
Ключевое слово — уникальные: один user_id считаем один раз, сколько бы раз он ни заходил.


2️⃣ Считаем все три одним запросом
SELECT
COUNT(DISTINCT CASE WHEN dt = CURRENT_DATE THEN user_id END) AS dau,
COUNT(DISTINCT CASE WHEN dt >= CURRENT_DATE - 6 THEN user_id END) AS wau,
COUNT(DISTINCT CASE WHEN dt >= CURRENT_DATE - 29 THEN user_id END) AS mau
FROM events;

COUNT(DISTINCT …) убирает повторы, CASE WHEN задаёт окно по дате.


3️⃣ Частая ошибка
WAU — это не сумма семи DAU. Кто заходил все 7 дней, в сумме DAU посчитан 7 раз, а в WAU — один.
Отсюда правило: DAU ≤ WAU ≤ MAU.


4️⃣ Sticky factor
sticky factor = DAU / MAU — показывает, как часто пользователи возвращаются.
0.1 → заходят ~3 дня в месяц (слабо)
0.2 → ~6 дней
0.5 → ~15 дней (уровень соцсетей)
Чем выше — тем «липче» продукт.


Итог: 🤩  

❤️ Поддержать канал бустами, чтобы у автора появился дополнительный функционал можно - здесь (это бесплатно и доступно с подпиской telegram premium)
  Как вам такие разборы в формате видео? Делись в комментариях!
✔️ Подпишитесь на канал, чтобы не пропустить следующие хаки.


🚬 Вопросы, обучение, консультации:  Написать в ЛС | mentor.dima-sqlit.ru 


@dima_sqlit
Please open Telegram to view this post
VIEW IN TELEGRAM
❤‍🔥20🔥16🐳7
This media is not supported in your browser
VIEW IN TELEGRAM
🎲 Формула Байеса и условная вероятность — разбор на кубике:

Условие: кинули кубик и говорят — выпало чётное. Какова вероятность, что это шестёрка?

Ответ: не 1/6, а 1/3. Покажу через формулу Байеса и расшифрую в ней каждое слагаемое — это и есть самое главное.

1️⃣ Обозначим события:
A — «выпала шестёрка» (это мы ищем)
B — «выпало чётное» (это уже известно — условие)
Нужна вероятность A, если известно B.


2️⃣ Сама формула Байеса:
P(A|B) = P(B|A) × P(A) / P(B)
Читается: вероятность A при условии, что произошло B.


3️⃣ Разбираем каждый кусок формулы:
• P(A|B) — что ищем: шанс шестёрки, раз выпало чётное. Это и есть ответ.
• P(A) — базовый шанс шестёрки, без подсказок = 1/6.
• P(B) — шанс чётного вообще: чётные это 2, 4, 6, то есть 3 из 6 = 1/2.
• P(B|A) — шанс, что чётное, ЕСЛИ выпала шестёрка = 1. Шестёрка всегда чётная.


4️⃣ Подставляем числа:
P(A|B) = P(B|A) × P(A) / P(B) = 1 × (1/6) / (1/2) = (1/6) / (1/2) = 1/3


5️⃣ Почему получилось именно так:
Подсказка «чётное» выкинула варианты 1, 3, 5. Осталось 2, 4, 6 — и шестёрка одна из трёх. Формула дала ровно это: 1/3. Информация подняла шанс шестёрки с 1/6 до 1/3 — в этом вся суть Байеса.

Итог: 🤩  

❤️ Поддержать канал бустами, чтобы у автора появился дополнительный функционал можно - здесь (это бесплатно и доступно с подпиской telegram premium)
  А вы сразу сказали 1/3 или попались на 1/6? Делитесь в комментариях!
✔️ Подпишитесь на канал, чтобы не пропустить следующие разборы.


🚬 Вопросы, обучение, консультации:  Написать в ЛС | mentor.dima-sqlit.ru 


@dima_sqlit
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥11❤‍🔥4🐳4
This media is not supported in your browser
VIEW IN TELEGRAM
💰 ARPU vs ARPPU — разберемся в чем разница:

ARPU и ARPPU постоянно путают. Обе про доход с пользователя, но делят на разное. Разберём и выведем главную формулу.

1️⃣ ARPU — доход на ВСЕХ
Всю выручку делим на всех активных, даже на тех, кто ничего не заплатил.
ARPU = выручка / все юзеры
SELECT
SUM(revenue) / COUNT(DISTINCT user_id) AS arpu
FROM payments;


2️⃣ ARPPU — доход на ПЛАТЯЩИХ
Та же выручка, но делим только на тех, у кого платёж больше нуля.
ARPPU = выручка / платящие
SELECT
SUM(revenue) / COUNT(DISTINCT CASE WHEN revenue > 0 THEN user_id END) AS arppu
FROM payments;


3️⃣ Связь — доля платящих
доля платящих = платящие / все юзеры = CR to pay (часто 1–5%)
Отсюда главное тождество:
ARPU = ARPPU × доля платящих
И всегда ARPPU >= ARPU.

4️⃣ Куда расти
Тождество показывает два рычага роста:
• поднять долю платящих — онбординг, триггеры оплаты
• поднять ARPPU — апселл, тарифы, допродажи

Итог: 🤩  

❤️ Поддержать канал бустами, чтобы у автора появился дополнительный функционал можно - здесь (это бесплатно и доступно с подпиской telegram premium)
  Что еще разобрать? Пишите в комментариях!
✔️ Подпишитесь на канал, чтобы не пропустить следующие хаки.


🚬 Вопросы, обучение, консультации:  Написать в ЛС | mentor.dima-sqlit.ru 


@dima_sqlit
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥16🐳7❤‍🔥4
This media is not supported in your browser
VIEW IN TELEGRAM
🏦  Разбор задачи с собеседования в Т-Банке (Тинькофф). Тест точен на 99%, он положительный — но вы, скорее всего, здоровы:

Ранее мы разобрали, как работает условная вероятность и формула Байеса.
Если пропустили, то вот сам пост.

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

Условие: болезнь встречается у 1% людей. Тест находит болезнь у больного в 99% случаев, а у здорового ошибочно кричит «+» в 5% случаев. Вам пришёл положительный результат. Какова вероятность, что вы действительно больны?

Почти все на автомате отвечают «99%». Правильный ответ — 16.7%. Разберём, почему.

1️⃣ Вопрос не тот, на который вы ответили:
В условии дано P(+ | болен) = 99% — «тест сработает, если человек болен».
А спрашивают P(болен | +) — «человек болен, если тест сработал».

Это разные вопросы, и цифры у них разные. Формула Байеса как раз переворачивает условную вероятность с одной стороны на другую.


2️⃣ Считаем по головам — 10 000 человек:
Забудем про проценты и посчитаем живых людей:
• больных: 1% от 10 000 = 100 человек
• здоровых: 9 900 человек

Прогоняем всех через тест:
• из 100 больных тест поймает 99% = 99 человек
• из 9 900 здоровых тест ошибочно испугает 5% = 495 человек

тест + тест − всего
болен 99 1 100
здоров 495 9405 9900
всего 594 9406 10000

Смотрим столбец «тест +»: плюс получили 594 человека, а больны из них только 99.

P(болен | +) = 99 / 594 = 1/6 ≈ 16.7%


3️⃣ Тот же ответ формулой Байеса:
Сначала выпишем всё, что даёт условие — новых чисел дальше не появится:

P(болен) = 0.01 — болезнь у 1% людей
P(здоров) = 0.99 — остальные 99%
P(+ | болен) = 0.99 — тест ловит больного
P(+ | здоров) = 0.05 — ошибка на здоровом

⚠️ Два разных числа выглядят одинаково: 0.99 — это и точность теста, и доля здоровых. Не перепутайте, кто где стоит.

Числитель — только больные с плюсом:
P(болен) × P(+|болен) = 0.01 × 0.99 = 0.0099 → это наши 99 человек

Знаменатель — почему он именно такой
Мы ищем долю: из всех, у кого плюс, сколько по-настоящему больны. Значит внизу должны стоять ВСЕ плюсы, а не только больные — иначе это будет не доля.

А плюс может прийти ровно из двух мест:
• тест поймал больного → 0.01 × 0.99 = 0.0099 → 99 человек
• тест ошибся на здоровом → 0.99 × 0.05 = 0.0495 → 495 человек

Третьего источника нет: человек либо болен, либо здоров, других вариантов не бывает. Поэтому знаменатель — сумма этих двух групп (это и есть формула полной вероятности):

P(+) = 0.0099 + 0.0495 = 0.0594 → 594 человека

Внутри каждой группы мы умножаем по одному правилу: «какая группа по размеру» × «какая доля в ней даёт плюс». Для здоровых это 0.99 × 0.05 — 99% людей здоровы, и 5% из них тест пугает зря.

Делим: 0.0099 / 0.0594 ≈ 0.167 = 16.7%

Ровно те же 99 и 594, что мы посчитали по головам. Формула ничего не выдумывает — она просто записывает подсчёт людей на языке вероятностей.



Итог: 🤩  

❤️ Поддержать канал бустами, чтобы у автора появился дополнительный функционал можно - здесь (это бесплатно и доступно с подпиской telegram premium)
  Встречали эту задачку на собеседованиях? Пишите в комментариях!
✔️ Подпишитесь на канал, чтобы не пропустить следующие хаки.


🚬 Вопросы, обучение, консультации:  Написать в ЛС | mentor.dima-sqlit.ru 


@dima_sqlit
Please open Telegram to view this post
VIEW IN TELEGRAM
❤‍🔥11🔥10🐳4