🧙MagicSQL💻
160 subscribers
185 photos
7 files
10 links
Войди в мир SQL и аналитики с моим каналом. Изучай, применяй и преуспевай. Интересный контент, задачи, тесты, разборы и обучение.
#SQL #базыданных #postgresql
Download Telegram
👍6🔥4👏1
5 лет назад я даже не понимал для чего нужен SQL.
По просьбе ребят, подготовил краткую шпаргалку.

🧭 Как не забыть SQL после курса ?

1. Практикуйся каждый день

SQL — это навык, который держится на регулярности.
10–20 минут в день уже дают результат.
Используй тренажёры, например:

SQLZoo
LeetCode SQL
Hackerrank SQL

2. Повторяй материал курса

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

3. Веди “SQL-дневник”

После каждой практики запиши коротко:
Что повторил или узнал
Что вызвало трудности
Один полезный приём или запрос

Так создашь личную базу знаний и мотивации.

4. Повторяй темы циклично

Раз в неделю пробегай ключевые блоки:
SELECT → JOIN → GROUP BY → подзапросы → оконные функции
Постоянное повторение — основа уверенности.

5. Применяй SQL в жизни

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

Регулярность важнее длительности. Главное — не прекращать.
❤4
💬 Стоит ли использовать ИИ в работе и обучении?

Меня часто спрашивают:
можно ли вообще использовать ИИ для работы или обучения?

Отвечаю — можно и нужно.
Но важно — делать это с головой.

ИИ реально помогает: ускоряет задачи, подкидывает идеи, помогает учиться.
Но есть нюанс — он не несёт ответственности.
Ошибся не ИИ, а ты. Спрашивать будут с нас.

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

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

И вот еще один важный интересный момент:
ИИ ведь учится у людей, учится на данных, на тех же к нему запросах (промтах).
Если человек со временем перестанет думать, разбираться и учиться — то и ИИ станет глупее.
Мы фактически учим его своим мышлением.
Так что, чтобы ИИ развивался, умнеть должны мы сами.

Поэтому ИИ не должен «разучивать» нас — наоборот, он должен мотивировать учиться ещё больше, чтобы использовать его максимально эффективно.

ИИ — не замена эксперту.
Он — ускоритель эксперта 🚀
👍3
🎓 7 строковых функций в PostgreSQL, которые стоит знать каждому аналитику.

🔹 1. LOWER / UPPER — меняют регистр текста

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

SELECT
LOWER('PostgreSQL'),
-- postgresql
UPPER('sql rocks'); -- SQL ROCKS

🔹 2. CONCAT и || — объединяют строки

Но будь внимателен ⚠️: CONCAT() игнорирует NULL,
а || вернёт NULL, если хотя бы один аргумент NULL.

SELECT
CONCAT('Ivan', ' ', 'Petrov'),
-- Ivan Petrov
CONCAT('Ivan', ' ', NULL), -- Ivan
'Ivan' || ' ' || 'Petrov', -- Ivan Petrov
'Ivan' || ' ' || NULL; -- NULL ⚠️

🔹 3. SPLIT_PART — разделяет строку по разделителю

Укажи строку, символ-разделитель и номер части, которую хочешь получить.

SELECT
SPLIT_PART('ivan.petrov@example.com', '@', 1),
-- ivan.petrov
SPLIT_PART('ivan.petrov@example.com', '@', 2); -- example.com

🔹 4. SUBSTRING — достаёт часть строки

Работает по позиции и длине: “начало” и “сколько символов”.

SELECT
SUBSTRING('2025-10-21' FROM 1 FOR 4),
-- 2025
SUBSTRING('Analytics' FROM 4 FOR 3); -- lyt

🔹 5. LEFT — возвращает первые n символов

Когда нужно взять только начало строки.

SELECT
LEFT('PostgreSQL', 4);
-- Post

🔹 6. RIGHT — возвращает последние n символов

Помогает достать “хвост” строки — например, окончание кода или номера.

SELECT
RIGHT('PostgreSQL', 3);
-- SQL
👍4
🎯 SQL-фишка дня: подзапрос в WHERE

Иногда нужно выбрать строки на основе данных из другой таблицы. В таких случаях выручает подзапрос в выражении WHERE👇

🔹 Пример с IN

SELECT *
FROM orders
WHERE customer_id IN (
SELECT id
FROM customers
WHERE country = 'Germany'
);


🧠 Что происходит:
— внутренний подзапрос возвращает всех клиентов из Германии
— внешний выбирает все заказы этих клиентов, сравнивая поле customer_id внешнего запроса с полем id подзапроса

🔹 А теперь наоборот — NOT IN

SELECT *
FROM orders
WHERE customer_id NOT IN (
SELECT id
FROM customers
WHERE country = 'Germany'
);


💡 Здесь мы получим все заказы клиентов, которые НЕ из Германии.
❤6
🎯 Мультимодельные базы данных — когда одной модели уже мало

Традиционно системы управления базами данных строились вокруг одной модели данных:

реляционной (таблицы),

документной (JSON),

графовой (узлы и связи).

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

Это упрощает администрирование, ускоряет аналитику и снижает сложность архитектуры.
Некоторые традиционные реляционные СУБД тоже движутся в этом направлении, добавляя поддержку JSON, графов и других структур данных.

Примеры мультимодельных СУБД: ArangoDB, OrientDB, Couchbase.
👍5
☕️ SQL — как заказать кофе

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

Он декларативный: ты формулируешь результат,
а база данных сама решает, как его достичь.

Если бы ты заказывал кофе в стиле SQL 👇

SELECT coffee — что заказать
FROM coffee_shop — где заказать
WHERE sugar = false — без сахара
AND payer = 'Петя' — а платит Петя :)
GROUP BY friend; — каждому по кофе


Ты не говоришь бариста, как молоть зёрна или варить кофе.
Ты просто декларируешь результат:

«Хочу кофе без сахара, за счёт Пети, как обычно у нас в компании».

SQL — язык ясных намерений и доверия к исполнителю.
База данных, как идеальный бариста, сделает всё сама ☕️
❤3👍2🔥1
💼 5 навыков, кроме SQL, которые сегодня ищут работодатели

Российский рынок труда переживает кадровый дефицит:
безработица в октябре 2025 года составляет всего 2–3 % — исторический минимум. Компании конкурируют за специалистов, особенно в IT, инженерии и аналитике.

Но “просто знать SQL” не достаточно, хоть это и отправная точка— сегодня нужны аналитики с комплексным техническим и бизнес-бэкграундом.

🔹 1. Python и автоматизация анализа данных

Python стал стандартом для аналитиков в России —
почти половина вакансий включает его в обязательные навыки.
Также востребованы R, pandas, NumPy и библиотеки машинного обучения.

🔹 2. BI-инструменты (Power BI, Yandex DataLens, Tableau)

Бизнес активно переходит на визуальную аналитику.
Особенно растёт популярность Yandex DataLens — за счёт локализации и интеграции с экосистемами Яндекса.

🔹 3. Бизнес-анализ и постановка задач

Аналитиков всё чаще нанимают на стыке бизнеса и IT.
Важно уметь понимать метрики, воронки продаж, ROI и продуктовые цели.

🔹 4. Визуализация и сторителлинг с данными

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

🔹 5. Мягкие навыки (soft skills)

Критическое мышление, коммуникация, самообучение.
Современные аналитики работают в кросс-функциональных командах — умение отстаивать свои выводы и говорить на языке бизнеса становится не менее важным, чем владение SQL.

💬 Итог: чтобы быть востребованным аналитиком в 2025 году,
нужно сочетать инструменты, логику и умение объяснять данные людям.
💯3❤1👍1
Всем привет. Понедельник день тяжелый. Сделаю его еще тяжелее 😇. Вопрос: Какой из запросов гарантированно вернет все строки из таблицы (при условии что в таблице действительно есть строки) ?
Anonymous Quiz
19%
SELECT * FROM orders where 1 = NULL;
4%
SELECT * FROM orders WHERE 1 = 0;
0%
SELECT * FROM orders WHERE order_id > 5;
31%
SELECT * FROM orders where 1 <> NULL;
35%
SELECT * FROM orders where 1 = 1;
12%
SELECT * FROM orders where NULL = NULL;
⚙️ Функция COALESCE — простая подстановка значений в SQL

Когда в таблице встречаются NULL, логика запросов ломается.
Функция COALESCE помогает “подставить” значение по умолчанию, если значения отсутствуют, то есть вместо них NULL.

🔹 Как работает

SELECT COALESCE (NULL, 'default'); -- вернёт 'default'
SELECT COALESCE ('данные', 'default'); -- вернёт 'данные'

COALESCE просто берёт первое не-NULL значение из списка аргументов.

🔹 Пример:

SELECT name,
COALESCE (phone, '— нет телефона —') AS phone_display
FROM clients;


Если в поле phone встретятся значения NULL, то вместо них выведется фраза: — нет телефона —.

🔹 Несколько значений:

SELECT COALESCE(email, backup_email, '— нет контактов —') AS contact
FROM users;


Здесь функция проверяет значения полей, заданных в скобках по порядку: email → backup_email → '— нет контактов —'.

🧠
COALESCE — это страховка от NULL,
и её можно использовать почти везде: в SELECT, ORDER BY, GROUP BY, даже в UPDATE.
Вообщем это очень крутая функция, знать о которой обязательно.
👍4
Всем привет.

Разбор позавчерашнего вопроса про возврат строк из таблицы. Решил, что это нужно разобрать, так как работа с NULL не всегда выдает очевидное — чаще как раз наоборот.

1. SELECT * FROM orders WHERE 1 = NULL;

Это условие никогда не выполнится, потому что любые сравнения с NULL, включая 1 = NULL, всегда дают результат UNKNOWN, и такие строки не попадают в результат запроса.​ Другими словами нельзя сравнивать существующее значение с NULL, результат всегда будет FALSE.

2. SELECT * FROM orders WHERE 1 = 0;

Это условие всегда возвращает FALSE, ни одна строка не будет выбрана, запрос вернет пустой результат, даже если строки есть.​ Просто потому что, 1 не равно 0.

3. SELECT * FROM orders WHERE order_id > 5;

Этот запрос вернет только те строки, где order_id больше 5, а значит не гарантирует возврат всех строк таблицы, если есть строки с order_id ≤ 5.​

4. SELECT * FROM orders WHERE 1 <> NULL;

Аналогично первому варианту, сравнение с NULL (1 <> NULL) всегда возвращает UNKNOWN. В результате ни одна строка не будет выбрана.​

5. SELECT * FROM orders WHERE 1 = 1; ✅

Это условие всегда истинно, независимо от содержимого строки: каждая строка будет возвращена, поэтому этот вариант гарантировано возвращает все строки из таблицы, если они в ней есть.​

6. SELECT * FROM orders WHERE NULL = NULL;

Как и в предыдущих сравнениях с NULL, результат всегда UNKNOWN, ни одна строка не попадает в выборку — гарантировано пусто.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
🧨 Почему SELECT * — это зло, и PostgreSQL тебе этого не простит ?

Когда ты пишешь SELECT *, где-то внутри PostgreSQL тихо плачет планировщик 😢 Потому что вместо одного красивого запроса ты запускаешь комбайн по растаскиванию кучи строк.

Вот почему:

1️⃣ Хеш-таблица при алгоритме соединения Hash Join пухнет до параметра work_mem (параметр, выделяющий память для обработки запросов).

Если ты делаешь JOIN, Postgres может выбрать алгоритм соединения Hash Join, как один из алгоритмов и хеш таблица будет построена по всем выбранным колонкам.
Когда ты ставишь *, туда летит всё подряд.
Результат — work_mem забит, планировщик начинает спиллинг на диск, и “быстрый” JOIN идёт пить кофе ☕️

2️⃣ TOAST говорит: “Приятного аппетита!”

Postgres хранит длинные значения (TEXT, JSONB и т.д.) в TOAST-таблицах. TOAST - это такая специальная технология для хранения больших значений в отдельных таблицах.
Если ты выбираешь *, он вытаскивает их в любом случае, даже если тебе нужно только id. То есть ты сам зовёшь на ужин все 10-гигабайтные тексты, которые никто не ел 🤦‍♂️

3️⃣ INDEX ONLY SCAN? Нет, не слышали.

INDEX ONLY SCAN - оптимизация при которой нужные в результате столбцы есть в самом индексе. То есть возможно не нужно обращаться к самой таблице, а достать все данные из самого индекса, работает очень быстро и эффективно.
Но SELECT * ломает эту оптимизацию — Postgres вынужден идти в heap (кучу строк), чтобы достать остальные поля.
И твой быстрый запрос превращается в медленный.

4️⃣ Лишние данные = лишняя нагрузка

Сеть, CPU, память — всё страдает.
Даже если приложение потом использует 2 поля из 20, Postgres всё равно тащит весь мешок данных и заботливо складывает тебе в ответ.

5️⃣ Буферный кеш засоряется

Postgres кеширует страницы данных в специальных буферах, для эффективного обмена нужными данными.
Когда ты выбираешь *, кеш наполняется ненужными колонками.
А потом, когда реально нужный запрос приходит — места уже нет 🤷‍♂️

💡 Вывод:

SELECT * — это как “всё включено” в отеле, где ты ешь один салат, но платишь за омаров, вино и шоу с фаерболами.
Пиши явно, что тебе нужно. PostgreSQL скажет “спасибо” и даст красивый план с INDEX ONLY SCAN.

Наверное многие слышали что * это плохо, но мало кто понимает почему. Это конечно не простая тема, если будут вопросы по пунктам пишите, буду пояснять.
👍3👏2
📦 Что происходит, когда ты нажимаешь «Оформить заказ» (или меняешь данные в личном кабинете на сайте).

Ты жмёшь кнопку «Купить», и кажется — всё, магия! ✨
Но на самом деле под капотом запускается целая цепочка событий,
в которой участвуют браузер, сервер и база данных PostgreSQL.

Разберёмся пошагово 👇

🖱 1. Ты нажал кнопку на сайте

Браузер (например, Chrome) отправляет запрос серверу сайта.
Что-то вроде:

POST /order

Внутри — всё нужное: товар, количество, адрес доставки, твой логин.

Браузер не идёт напрямую в базу, он просто говорит серверу:

«Эй, вот заказ от пользователя №123!»

⚙️ 2. Сервер получает запрос и решает, что делать

На сервере работает программа (например, на Python, Node.js, PHP или Java).

Она:

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

Примерно так:

INSERT INTO orders (user_id, product_id, quantity, address)
VALUES (123, 42, 2, 'ул. Примерная, д.7');


🧩 3. Сервер общается с PostgreSQL

Теперь приложение подключается к PostgreSQL (по внутреннему протоколу) и говорит:

«Postgres, вот SQL-запрос — запиши новый заказ!»

PostgreSQL принимает запрос, проверяет права и создаёт новую запись в таблице orders.

🧠 4. PostgreSQL обрабатывает запрос

Под капотом Postgres делает кучу работы:

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

Когда всё готово, он отвечает серверу:

«Всё, я сохранил заказ ✅»

📤 5. Сервер отправляет ответ браузеру

Сервер формирует ответ:

{"status": "ok", "message": "Заказ оформлен"}

и отправляет его обратно в браузер. А браузер показывает тебе красивую страницу:

«Спасибо за заказ!» 💙

💡 Итого:

Каждый раз, когда ты что-то делаешь на сайте —
оформляешь заказ, редактируешь профиль или ставишь лайк —
данные проходят длинный путь:
браузер → сервер → PostgreSQL → обратно к тебе на экран.

Никакой магии. Просто хорошо отлаженная система 💪
❤3
🧩 CASE WHEN — гибкая логика прямо в SQL.

CASE WHEN — это способ добавить в SQL немного “ума”.
Он позволяет выполнять условия прямо в запросах:
выбирать разные значения в зависимости от данных,
похож на конструкцию if...else в обычных языках программирования.

🧠 Когда используется CASE WHEN ?

- когда нужно преобразовать значения на лету;
- когда нужно разделить данные на категории;
- когда хотите добавить логику без подзапросов.

💡 Пример:

Допустим, у нас есть таблица пользователей users с количеством их публикаций — posts_count.
Нам нужно вывести, насколько активен каждый пользователь.

SELECT
username,
posts_count,
CASE
WHEN posts_count >= 20 THEN '🔥 Активный автор'
WHEN posts_count BETWEEN 5 AND 19 THEN '🙂 Иногда пишет'
ELSE '💤 Почти неактивен'
END AS activity_level
FROM users;


🔍 Разбор:

CASE WHEN проверяет условия сверху вниз.
Сначала смотрим, есть ли у пользователя 20 и больше постов.
Если да — возвращаем '🔥 Активный автор'.

Если нет — проверяем следующее условие: от 5 до 19 постов.
Подходит? Тогда '🙂 Иногда пишет'.

Если не сработало ни одно условие — выполняется ELSE, и возвращаем '💤 Почти неактивен'.

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

🧩 Итого

CASE WHEN — отличный инструмент, когда нужно добавить гибкую логику прямо в SQL.
Используйте его, чтобы:

- превращать цифры в осмысленные статусы,
- управлять порядком сортировки,
- или просто делать запросы “умнее”.
🔥2👍1
Не сравнивай свой прогресс с чужим.

Кто-то уже пишет сложные CTE и использует оконные функции, а ты всё ещё осваиваешь базовые JOIN — и это абсолютно нормально!

Учёба — не гонка. У каждого свой темп, свой стиль мышления и свой путь. Главное не просто повторять за другими, а реально понимать, как работают запросы и почему они нужны.


SQL — отличный инструмент для работы с данными, и его можно изучать шаг за шагом:

Сначала пройди основы: SELECT, FROM, WHERE, GROUP BY, HAVING, ORDER BY.

После того как простые запросы станут привычными, переходи к JOIN, учись объединять данные из разных таблиц.

Потом попробуй CTE (WITH) и оконные функции — они пригодятся для сложных задач.

Мотивационная инструкция:

Ставь реалистичные цели на неделю или месяц (например, освоить один тип JOIN или научиться писать простой SELECT с GROUP BY)

Практикуйся регулярно — даже 20 минут в день

Не стесняйся ошибаться, пробуй разные подходы

Старайся учиться на задачах, которые тебе интересны и полезны

Окружай себя поддержкой: общайся с единомышленниками, участвуй в сообществе и делись успехами

Если кажется, что идёшь медленно — это иллюзия! Ты уже знаешь гораздо больше, чем вчера, и движешься к своей цели.
👍3❤1
Всем привет. Загадка.

В таблице products есть колонки id, name, category, price. Какой из запросов вернёт товары, стоимостью больше 1000, которые принадлежат к категории 'Books' или 'Electronics' ?
Anonymous Quiz
43%
SELECT * FROM products WHERE category = 'Books' OR category = 'Electronics' AND price > 1000;
33%
SELECT * FROM products WHERE (category = 'Books' OR category = 'Electronics') AND price > 1000;
0%
SELECT * FROM products WHERE category = 'Books' AND category = 'Electronics' OR price > 1000;
19%
SELECT * FROM products WHERE category = 'Books' AND category = 'Electronics' AND price > 1000;
5%
Ни один из вариантов ответа;
💣 Атомарность транзакций — “всё или ничего” в действии.


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

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

Чтобы база оставалась надёжной, транзакции подчиняются четырём свойствам — ACID:

A — Atomicity (атомарность) — всё или ничего
C — Consistency (согласованность)
I — Isolation (изолированность)
D — Durability (надёжность, сохранность)

Сегодня разберём первую букву — атомарность 👇

⚙️ Что значит “атомарно”

Атомарность (Atomicity) — это гарантия, что транзакция выполнится полностью или не выполнится вовсе. Если где-то посередине произошёл сбой (например, свет моргнул, сеть отвалилась, диск не ответил) — PostgreSQL откатит всё, как будто ничего не происходило.

💰 Пример с переводом денег:

BEGIN;

UPDATE accounts SET balance = balance - 100 WHERE id = 1; — списываем деньги с одного счета

UPDATE accounts SET balance = balance + 100 WHERE id = 2; — зачисляем на другой счет

COMMIT;


💡 Если всё прошло успешно — COMMIT зафиксирует изменения в базе.
💥 Если один из шагов упадёт (например, второй UPDATE не выполнится) — PostgreSQL автоматически откатит транзакцию:

сделает ROLLBACK;

И оба счёта останутся без изменений.
То есть либо оба действия проходят, либо ни одно.

🧠 Почему это важно

Без атомарности могли бы быть такие “чудеса”:

со счёта A деньги списались,

на счёт B — не пришли.

И всё, нормальное состояние базы данных нарушено.

Атомарность спасает от этого, гарантируя, что база данных никогда не окажется “наполовину обновлённой”.

⚡️
Итого

Атомарность — это “всё или ничего”.

PostgreSQL делает так, чтобы любая операция внутри транзакции была неделимой и безопасной.
❤4👍3
Разбор загадки: логические OR и AND.

На первый взгляд кажется, что правильный вариант —

SELECT * FROM products WHERE category = 'Books' OR category = 'Electronics' AND price > 1000;



но... это не так 😏

⚙️ Что происходит на самом деле

SQL, как и большинство языков, имеет приоритет операторов.
AND выполняется раньше, чем OR.

Поэтому запрос читается вот так:

WHERE category = 'Books' OR (category = 'Electronics' AND price > 1000)



А значит — в результат попадут:

все товары из категории Books (независимо от цены),
и только те товары из Electronics, где price > 1000.
💥 То есть дешёвые книги тоже окажутся в выборке, которые стоят меньше 1000.


✅ Правильный вариант

Чтобы выбрать товары только дороже 1000 и из двух категорий, нужно "изолировать" условия скобками:

SELECT * FROM products 
WHERE (category = 'Books' OR category = 'Electronics') AND price > 1000;



Теперь порядок вычисления ясен:
1️⃣ выбираются категории Books или Electronics,
2️⃣ применяется фильтр по цене, но именно к одной из категорий в скобках.

🧠 Почему это важно

Такие мелочи часто ломают бизнес-логику:

в отчёте появляются лишние строки,

фильтры работают “почти правильно”,

разработчик уверен, что всё ок — пока аналитик не замечает странные данные.

SQL не “угадывает” твои намерения — он строго следует приоритетам операторов.


💡 Вывод

AND сильнее OR.
Если хочешь, чтобы условия работали как тебе нужно —
ставь скобки и не надейся на интуицию.
❤4👍4
Разберем полезный инструмент, а именно как CASE помогает решать подобные задания.


Имеется таблица отзывов пользователей маркетплейса о купленных товарах.
У каждого отзыва есть оценка в звёздах.
Нужно посчитать, какой процент отзывов имеет оценку «2» относительно общего количества — в одном SQL-запросе.

SELECT 
count(review_id) AS общее_количество,
count(CASE WHEN stars = 2 THEN review_id END) AS количество_с_оценкой_2,
round(count(CASE WHEN stars = 2 THEN review_id END)::numeric / count(review_id) * 100, 2) AS процент
FROM market.reviews r;


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

- `CASE WHEN stars = 2 THEN review_id END` возвращает `review_id` только для тех строк, где оценка равна 2,
для остальных возвращается — `NULL`.
- Функция `count()` не считает `NULL`, поэтому получается только количество отзывов с оценкой 2.
- Делим count(CASE WHEN stars = 2 THEN review_id END) на общее количество строк count(review_id) и умножаем на 100 — получаем процент.
- `round(..., 2)` округляет результат до двух знаков после запятой.

В итоге одним запросом получаем сразу три показателя: общее количество отзывов, количество с оценкой 2 и их долю в процентах.
👍6❤2