Полная теория SQL для Data Analyst (на базе Northwind)


1. Базовые SELECT запросы

Теория

SELECT — основа всех запросов в SQL. Позволяет выбирать данные из таблиц.

SELECT столбцы FROM таблица WHERE условия;

Ключевые элементы

Элемент

Описание

Пример

SELECT *

Выбрать все столбцы

SELECT * FROM customers

SELECT column1, column2

Выбрать конкретные столбцы

SELECT company_name, country FROM customers

SELECT DISTINCT

Убрать дубликаты

SELECT DISTINCT country FROM customers

WHERE

Фильтрация строк

WHERE country = 'USA'

AND/OR

Логические операторы

WHERE country = 'USA' AND city = 'Portland'

IN

Проверка на вхождение

WHERE country IN ('USA', 'Canada', 'UK')

BETWEEN

Диапазон значений

WHERE unit_price BETWEEN 10 AND 50

LIKE

Поиск по шаблону

WHERE product_name LIKE '%Chai%'

IS NULL

Проверка на NULL

WHERE region IS NULL

ORDER BY

Сортировка

ORDER BY order_date DESC

LIMIT

Ограничение количества строк

LIMIT 10

LIKE операторы

Оператор

Значение

%

Любое количество символов

_

Один символ

[a-z]

Диапазон символов (не во всех СУБД)

[^a-z]

Исключение (не во всех СУБД)

Примеры

-- Все продукты с ценой от 20 до 100
SELECT product_name, unit_price
FROM products
WHERE unit_price BETWEEN 20 AND 100;

-- Клиенты с email на gmail (если есть поле email)
SELECT company_name
FROM customers
WHERE contact_name LIKE '%@gmail.com';

-- Сотрудники, нанятые в 1993 году
SELECT first_name, last_name
FROM employees
WHERE EXTRACT(YEAR FROM hire_date) = 1993;

2. Агрегирующие функции и GROUP BY

Теория

Агрегирующие функции выполняют вычисления над набором строк и возвращают одно значение.

Функция

Описание

Пример

COUNT(*)

Количество строк

COUNT(*)

COUNT(column)

Количество не-NULL значений

COUNT(region)

COUNT(DISTINCT column)

Количество уникальных значений

COUNT(DISTINCT country)

SUM(column)

Сумма значений

SUM(unit_price * quantity)

AVG(column)

Среднее значение

AVG(unit_price)

MAX(column)

Максимальное значение

MAX(order_date)

MIN(column)

Минимальное значение

MIN(unit_price)

GROUP BY

Группирует строки с одинаковыми значениями для агрегации.

Важное правило: Все неагрегированные столбцы в SELECT должны быть в GROUP BY.

SELECT
    category_id,
    COUNT(*) as products_count,
    AVG(unit_price) as avg_price,
    MIN(unit_price) as min_price,
    MAX(unit_price) as max_price
FROM products
GROUP BY category_id;

Примеры

-- Количество заказов по сотрудникам
SELECT
    employee_id,
    COUNT(order_id) as orders_count,
    SUM(freight) as total_freight
FROM orders
GROUP BY employee_id
ORDER BY orders_count DESC;

-- Средняя сумма заказа по клиентам
SELECT
    customer_id,
    COUNT(order_id) as order_count,
    AVG(freight) as avg_freight
FROM orders
GROUP BY customer_id;

3. JOIN операции

Теория

JOIN объединяет данные из двух или более таблиц на основе связанных столбцов.

Типы JOIN

Тип

Описание

Диаграмма Венна

INNER JOIN

Только совпадающие строки в обеих таблицах

Пересечение

LEFT JOIN

Все строки из левой + совпадающие из правой

Левая + пересечение

RIGHT JOIN

Все строки из правой + совпадающие из левой

Правая + пересечение

FULL OUTER JOIN

Все строки из обеих таблиц

Объединение

CROSS JOIN

Декартово произведение

Все комбинации

Синтаксис

SELECT t1.column, t2.column
FROM table1 t1
[INNER | LEFT | RIGHT | FULL] JOIN table2 t2
    ON t1.key = t2.key;

Примеры

-- INNER JOIN: только заказы с клиентами
SELECT o.order_id, c.company_name
FROM orders o
INNER JOIN customers c ON o.customer_id = c.customer_id;

-- LEFT JOIN: все продукты, даже те, что не продавались
SELECT p.product_name, SUM(od.quantity) as total_sold
FROM products p
LEFT JOIN order_details od ON p.product_id = od.product_id
GROUP BY p.product_name;

-- Множественные JOIN
SELECT
    o.order_id,
    c.company_name,
    e.first_name || ' ' || e.last_name as employee_name,
    s.company_name as shipper_name
FROM orders o
INNER JOIN customers c ON o.customer_id = c.customer_id
INNER JOIN employees e ON o.employee_id = e.employee_id
INNER JOIN shippers s ON o.ship_via = s.shipper_id;

4. Подзапросы (Subqueries)

Теория

Подзапрос — это запрос внутри другого запроса SQL.

Типы подзапросов

Тип

Место использования

Пример

Скалярный

SELECT

SELECT (SELECT COUNT(*) FROM orders) as total_orders

Строковый

FROM

SELECT * FROM (SELECT ...) as sub

Табличный

WHERE/HAVING

WHERE column IN (SELECT ...)

Коррелированный

WHERE/EXISTS

WHERE EXISTS (SELECT 1 FROM ... WHERE ...)

Примеры

-- Подзапрос в WHERE: продукты дороже среднего
SELECT product_name, unit_price
FROM products
WHERE unit_price > (SELECT AVG(unit_price) FROM products);

-- Подзапрос с IN: клиенты из стран с заказами
SELECT company_name, country
FROM customers
WHERE country IN (
    SELECT DISTINCT ship_country
    FROM orders
);

-- Коррелированный подзапрос: сотрудники с заказами > среднего
SELECT
    employee_id,
    COUNT(order_id) as order_count
FROM orders o1
GROUP BY employee_id
HAVING COUNT(order_id) > (
    SELECT AVG(order_count)
    FROM (SELECT COUNT(*) as order_count
          FROM orders
          GROUP BY employee_id) as avg_orders
);

-- EXISTS: клиенты, которые делали заказы
SELECT company_name
FROM customers c
WHERE EXISTS (
    SELECT 1
    FROM orders o
    WHERE o.customer_id = c.customer_id
);

Коррелированные vs Некоррелированные

Тип

Описание

Производительность

Некоррелированный

Выполняется один раз

Лучше

Коррелированный

Выполняется для каждой строки внешнего запроса

Хуже


5. Оконные функции (Window Functions)

Теория

Оконные функции выполняют вычисления над набором строк, связанных с текущей строкой, без группировки (сохраняют все строки).

Синтаксис

Функция() OVER (
    [PARTITION BY column1, column2]  -- Разбиение на группы
    [ORDER BY column3, column4]       -- Порядок внутри группы
    [ROWS | RANGE между строками]     -- Определение окна
)

Классификация оконных функций

1. Ранжирующие функции

Функция

Описание

ROW_NUMBER()

Уникальный номер строки (1,2,3,4,5)

RANK()

Ранг с пропусками при связях (1,2,2,4,5)

DENSE_RANK()

Ранг без пропусков (1,2,2,3,4)

NTILE(n)

Разбивает на n групп

2. Агрегирующие оконные функции

Функция

Описание

SUM() OVER()

Накопительная сумма

AVG() OVER()

Скользящее среднее

COUNT() OVER()

Накопительный счетчик

MAX()/MIN() OVER()

Максимум/минимум в окне

3. Функции смещения

Функция

Описание

LAG(column, offset)

Доступ к предыдущей строке

LEAD(column, offset)

Доступ к следующей строке

FIRST_VALUE(column)

Первое значение в окне

LAST_VALUE(column)

Последнее значение в окне

Примеры

-- Ранжирование продуктов по цене в категории
SELECT
    product_name,
    category_id,
    unit_price,
    ROW_NUMBER() OVER (PARTITION BY category_id ORDER BY unit_price DESC) as row_num,
    RANK() OVER (PARTITION BY category_id ORDER BY unit_price DESC) as rank,
    DENSE_RANK() OVER (PARTITION BY category_id ORDER BY unit_price DESC) as dense_rank
FROM products;

-- Накопительная сумма (running total)
SELECT
    order_date,
    freight,
    SUM(freight) OVER (ORDER BY order_date) as running_total
FROM orders;

-- Скользящее среднее за 3 дня
SELECT
    order_date,
    freight,
    AVG(freight) OVER (ORDER BY order_date ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) as moving_avg_3
FROM orders;

-- LAG/LEAD: сравнение с предыдущим заказом
SELECT
    order_id,
    order_date,
    freight,
    LAG(freight, 1) OVER (ORDER BY order_date) as prev_freight,
    freight - LAG(freight, 1) OVER (ORDER BY order_date) as freight_diff
FROM orders;

-- Процент от общего
SELECT
    category_id,
    SUM(unit_price) as category_sum,
    SUM(unit_price) / SUM(SUM(unit_price)) OVER() * 100 as pct_of_total
FROM products
GROUP BY category_id;

Оконные функции vs GROUP BY

Характеристика

GROUP BY

Оконные функции

Количество строк

Уменьшается

Сохраняется

Использование

Простая агрегация

Сложные аналитические расчеты

Пример

Среднее по категориям

Ранжирование, скользящее среднее


6. Работа с датами

Теория

Функции для работы с датами различаются в разных СУБД.

PostgreSQL

Функция

Описание

Пример

EXTRACT(field FROM date)

Извлечение части даты

EXTRACT(YEAR FROM order_date)

DATE_TRUNC('unit', date)

Округление даты

DATE_TRUNC('month', order_date)

AGE(date1, date2)

Разница между датами

AGE(CURRENT_DATE, birth_date)

date1 - date2

Разница в днях

order_date - ship_date

date + INTERVAL

Добавление интервала

order_date + INTERVAL '30 days'

CURRENT_DATE

Текущая дата

CURRENT_DATE

NOW()

Текущие дата и время

NOW()

MySQL

Функция

Описание

Пример

YEAR(date)

Год

YEAR(order_date)

MONTH(date)

Месяц

MONTH(order_date)

DAY(date)

День

DAY(order_date)

DATE_ADD(date, INTERVAL)

Добавление интервала

DATE_ADD(order_date, INTERVAL 30 DAY)

DATEDIFF(date1, date2)

Разница в днях

DATEDIFF(order_date, ship_date)

DATE_FORMAT(date, format)

Форматирование

DATE_FORMAT(order_date, '%Y-%m')

Примеры

-- Извлечение частей даты
SELECT
    order_id,
    order_date,
    EXTRACT(YEAR FROM order_date) as year,
    EXTRACT(MONTH FROM order_date) as month,
    EXTRACT(DOW FROM order_date) as day_of_week,
    EXTRACT(QUARTER FROM order_date) as quarter
FROM orders;

-- Группировка по месяцам
SELECT
    DATE_TRUNC('month', order_date) as month,
    COUNT(*) as orders_count
FROM orders
GROUP BY DATE_TRUNC('month', order_date)
ORDER BY month;

-- Разница в днях
SELECT
    order_id,
    order_date,
    shipped_date,
    shipped_date - order_date as days_to_ship
FROM orders
WHERE shipped_date IS NOT NULL;

-- Возраст сотрудников
SELECT
    first_name,
    last_name,
    birth_date,
    AGE(CURRENT_DATE, birth_date) as age_interval,
    EXTRACT(YEAR FROM AGE(CURRENT_DATE, birth_date)) as age_years
FROM employees;

-- Фильтрация по дате
SELECT *
FROM orders
WHERE order_date BETWEEN '1997-01-01' AND '1997-12-31';

-- Добавление интервала
SELECT
    order_date,
    required_date,
    order_date + INTERVAL '7 days' as plus_7_days
FROM orders;

7. CASE выражения

Теория

CASE — условная логика в SQL (аналог IF-ELSE).

Синтаксис

CASE
    WHEN условие1 THEN результат1
    WHEN условие2 THEN результат2
    ELSE результат_по_умолчанию
END

Простой vs Поисковый CASE

Тип

Синтаксис

Когда использовать

Простой

CASE column WHEN value1 THEN result1

Равенство одному столбцу

Поисковый

CASE WHEN условие1 THEN result1

Сложные условия

Примеры

-- Классификация по цене
SELECT
    product_name,
    unit_price,
    CASE
        WHEN unit_price < 10 THEN 'Low'
        WHEN unit_price BETWEEN 10 AND 50 THEN 'Medium'
        WHEN unit_price > 50 THEN 'High'
        ELSE 'Unknown'
    END as price_category
FROM products;

-- Создание бакетов (группировка)
SELECT
    CASE
        WHEN EXTRACT(YEAR FROM AGE(birth_date)) < 30 THEN 'Junior'
        WHEN EXTRACT(YEAR FROM AGE(birth_date)) BETWEEN 30 AND 45 THEN 'Middle'
        ELSE 'Senior'
    END as age_group,
    COUNT(*) as employees_count
FROM employees
GROUP BY age_group;

-- Простой CASE
SELECT
    order_id,
    ship_country,
    CASE ship_country
        WHEN 'USA' THEN 'Domestic'
        WHEN 'Canada' THEN 'North America'
        WHEN 'Mexico' THEN 'North America'
        ELSE 'International'
    END as region
FROM orders;

-- PIVOT через CASE (транспонирование)
SELECT
    EXTRACT(YEAR FROM order_date) as year,
    SUM(CASE WHEN EXTRACT(MONTH FROM order_date) = 1 THEN freight ELSE 0 END) as jan,
    SUM(CASE WHEN EXTRACT(MONTH FROM order_date) = 2 THEN freight ELSE 0 END) as feb,
    SUM(CASE WHEN EXTRACT(MONTH FROM order_date) = 3 THEN freight ELSE 0 END) as mar
FROM orders
GROUP BY EXTRACT(YEAR FROM order_date);

-- CASE в ORDER BY
SELECT
    product_name,
    units_in_stock,
    discontinued
FROM products
ORDER BY
    CASE discontinued
        WHEN 1 THEN 1
        ELSE 0
    END,
    units_in_stock DESC;

8. CTE (Common Table Expressions)

Теория

CTE (WITH) — временный именованный набор результатов, существующий только в рамках одного запроса.

Синтаксис

WITH cte_name AS (
    SELECT ...
)
SELECT * FROM cte_name;

Преимущества CTE

Преимущество

Описание

Читаемость

Разбивает сложные запросы на логические блоки

Многократное использование

Можно использовать CTE несколько раз в запросе

Рекурсия

Поддержка рекурсивных запросов

Альтернатива подзапросам

Часто понятнее вложенных подзапросов

Примеры

-- Базовое CTE
WITH high_value_orders AS (
    SELECT
        order_id,
        customer_id,
        SUM(unit_price * quantity * (1 - discount)) as order_total
    FROM orders o
    INNER JOIN order_details od ON o.order_id = od.order_id
    GROUP BY order_id, customer_id
    HAVING SUM(unit_price * quantity * (1 - discount)) > 1000
)
SELECT
    c.company_name,
    COUNT(hvo.order_id) as high_value_orders_count
FROM high_value_orders hvo
INNER JOIN customers c ON hvo.customer_id = c.customer_id
GROUP BY c.company_name
ORDER BY high_value_orders_count DESC;

-- Множественные CTE
WITH
monthly_sales AS (
    SELECT
        DATE_TRUNC('month', order_date) as month,
        SUM(freight) as total_freight
    FROM orders
    GROUP BY DATE_TRUNC('month', order_date)
),
monthly_growth AS (
    SELECT
        month,
        total_freight,
        LAG(total_freight) OVER (ORDER BY month) as prev_month_freight
    FROM monthly_sales
)
SELECT
    month,
    total_freight,
    prev_month_freight,
    ROUND((total_freight - prev_month_freight) / prev_month_freight * 100, 2) as growth_pct
FROM monthly_growth
WHERE prev_month_freight IS NOT NULL;

-- Рекурсивное CTE (иерархия сотрудников)
WITH RECURSIVE employee_hierarchy AS (
    -- Anchor: базовый уровень
    SELECT
        employee_id,
        first_name || ' ' || last_name as employee_name,
        reports_to,
        0 as level
    FROM employees
    WHERE reports_to IS NULL

    UNION ALL

    -- Recursive: подчиненные
    SELECT
        e.employee_id,
        e.first_name || ' ' || e.last_name,
        e.reports_to,
        eh.level + 1
    FROM employees e
    INNER JOIN employee_hierarchy eh ON e.reports_to = eh.employee_id
)
SELECT
    LPAD(' ', level * 2) || employee_name as indented_name,
    level
FROM employee_hierarchy
ORDER BY level, employee_name;

CTE vs Подзапрос

Критерий

CTE

Подзапрос

Читаемость

Высокая

Снижается при вложенности

Многократное использование

Да

Нет (только копированием)

Рекурсия

Да

Нет

Область видимости

Только в запросе

В родительском запросе


9. HAVING vs WHERE

Теория

Ключевое слово

Когда применяется

Что фильтрует

WHERE

До GROUP BY

Отдельные строки

HAVING

После GROUP BY

Группы строк

Порядок выполнения запроса

1. FROM / JOIN
2. WHERE          ← фильтрация строк
3. GROUP BY       ← группировка
4. HAVING         ← фильтрация групп
5. SELECT
6. ORDER BY
7. LIMIT

Примеры

-- WHERE фильтрует до группировки
SELECT
    country,
    COUNT(*) as customers_count
FROM customers
WHERE country IN ('USA', 'Canada', 'UK')  -- фильтруем строки
GROUP BY country
HAVING COUNT(*) > 2;  -- фильтруем группы

-- Ошибка: нельзя использовать агрегацию в WHERE
-- WHERE COUNT(*) > 2  -- ОШИБКА!

-- Практический пример: продукты с ценой > 20,
-- у которых общая выручка > 5000
SELECT
    p.product_name,
    SUM(od.unit_price * od.quantity) as total_revenue
FROM products p
INNER JOIN order_details od ON p.product_id = od.product_id
WHERE p.unit_price > 20  -- фильтруем продукты ДО агрегации
GROUP BY p.product_name
HAVING SUM(od.unit_price * od.quantity) > 5000;  -- фильтруем после агрегации

10. Производительность запросов

Теория

Оптимизация SQL запросов критически важна для работы с большими объемами данных.

Индексы

Индекс — структура данных, ускоряющая поиск строк.

-- Создание индекса
CREATE INDEX idx_orders_customer_id ON orders(customer_id);
CREATE INDEX idx_orders_date ON orders(order_date);

-- Составной индекс
CREATE INDEX idx_orders_customer_date ON orders(customer_id, order_date);

-- Уникальный индекс
CREATE UNIQUE INDEX idx_customers_email ON customers(email);

Правила создания индексов:

Поле

Индексировать

Не индексировать

JOIN

Да

-

WHERE

Да

-

ORDER BY

Да

-

GROUP BY

Да

-

Мало уникальных значений

-

Нет (например, boolean)

Часто обновляемые

-

Нет (замедляет UPDATE)

Анализ запросов

-- PostgreSQL: анализ плана выполнения
EXPLAIN ANALYZE
SELECT * FROM orders WHERE customer_id = 'ALFKI';

-- Включение таймингов
EXPLAIN (ANALYZE, BUFFERS, TIMING)
SELECT * FROM orders WHERE customer_id = 'ALFKI';

Проблемные паттерны

Паттерн

Проблема

Решение

SELECT *

Избыточные данные

Указывать только нужные столбцы

LIKE '%text'

Не использует индекс

Избегать ведущего %

OR в условиях

Может не использовать индекс

Использовать UNION или IN

NOT IN с NULL

Неожиданные результаты

Использовать NOT EXISTS

Функции в WHERE

Не использует индекс

WHERE DATE(order_date) = '2023-01-01'WHERE order_date >= ...

Пример оптимизации

-- Медленный запрос
SELECT *
FROM orders o
INNER JOIN customers c ON o.customer_id = c.customer_id
WHERE c.country = 'USA'
  AND EXTRACT(YEAR FROM o.order_date) = 1997
  AND o.freight > 50;

-- Оптимизированный запрос
SELECT
    o.order_id,
    o.order_date,
    o.freight,
    c.company_name,
    c.contact_name
FROM orders o
INNER JOIN customers c ON o.customer_id = c.customer_id
WHERE c.country = 'USA'
  AND o.order_date >= '1997-01-01'
  AND o.order_date < '1998-01-01'
  AND o.freight > 50;

-- Создание индексов для оптимизации
CREATE INDEX idx_customers_country ON customers(country);
CREATE INDEX idx_orders_date_freight ON orders(order_date, freight);

11. Нормализация базы данных

Теория

Нормализация — процесс организации данных для уменьшения избыточности и зависимостей.

Нормальные формы

НФ

Определение

Нарушение

Решение

1NF

Атомарные значения, уникальные строки

Массив в ячейке

Вынести в отдельную таблицу

2NF

Нет частичных зависимостей (зависимость от части составного ключа)

(order_id, product_id) product_name

Вынести в отдельную таблицу

3NF

Нет транзитивных зависимостей (зависимость от неключевого поля)

product_id category_id category_name

Вынести категории в отдельную таблицу

Пример Northwind (3NF)

customers (customer_id PK)
    ↓
orders (order_id PK, customer_id FK)
    ↓
order_details (order_id PK, product_id PK)
    ↓
products (product_id PK, category_id FK, supplier_id FK)
    ↓                    ↓
categories (category_id PK)  suppliers (supplier_id PK)

Денормализация

Иногда для производительности намеренно нарушают нормализацию:

  • Создание витрин данных

  • Дублирование часто запрашиваемых полей

  • Предварительная агрегация


12. Типы данных в SQL

Основные типы

Категория

PostgreSQL

MySQL

Описание

Числовые

SMALLINT, INTEGER, BIGINT

TINYINT, INT, BIGINT

Целые числа

DECIMAL(p,s), NUMERIC

DECIMAL(p,s), NUMERIC

Точные десятичные

REAL, DOUBLE PRECISION

FLOAT, DOUBLE

Приближенные

Строковые

CHAR(n), VARCHAR(n)

CHAR(n), VARCHAR(n)

Фиксированная/переменная длина

TEXT

TEXT

Длинный текст

Дата/Время

DATE, TIME, TIMESTAMP

DATE, TIME, DATETIME

Дата, время, метка времени

INTERVAL

-

Интервалы

Булевы

BOOLEAN

BOOLEAN, TINYINT(1)

TRUE/FALSE

Бинарные

BYTEA

BLOB

Бинарные данные

Выбор типа данных

-- Правильно
customer_id   VARCHAR(5)    -- Фиксированный формат
unit_price    DECIMAL(10,2) -- Деньги требуют точности
quantity      SMALLINT      -- Не может быть отрицательным
order_date    DATE          -- Только дата, без времени
is_active     BOOLEAN       -- Только два значения

-- Неправильно
customer_id   TEXT          -- Избыточно
unit_price    FLOAT         -- Проблемы с округлением
quantity      VARCHAR(10)   -- Нельзя суммировать
order_date    TIMESTAMP     -- Избыточная точность
is_active     VARCHAR(3)    -- Допускает 'yes', 'no', 'Y'...

13. Транзакции и ACID

Теория

Транзакция — последовательность операций, выполняемая как единое целое.

ACID

Свойство

Описание

Пример

Atomicity (Атомарность)

Все операции выполняются или ни одна

Перевод денег: списание + зачисление

Consistency (Согласованность)

Данные остаются корректными

После перевода сумма не изменилась

Isolation (Изоляция)

Параллельные транзакции не влияют друг на друга

Два перевода не пересекаются

Durability (Долговечность)

Изменения сохраняются при сбое

После подтверждения данные не теряются

Уровни изоляции

Уровень

Dirty Read

Non-repeatable Read

Phantom Read

READ UNCOMMITTED

READ COMMITTED

REPEATABLE READ

SERIALIZABLE

Пример транзакции

BEGIN;

-- Создание заказа
INSERT INTO orders (customer_id, order_date, freight)
VALUES ('ALFKI', CURRENT_DATE, 20.00)
RETURNING order_id;

-- Добавление товаров в заказ
INSERT INTO order_details (order_id, product_id, unit_price, quantity, discount)
VALUES (100, 1, 18.00, 2, 0);

-- Обновление остатков
UPDATE products
SET units_in_stock = units_in_stock - 2
WHERE product_id = 1;

-- Проверка
SELECT * FROM products WHERE product_id = 1;

COMMIT;  -- или ROLLBACK при ошибке

14. Управление доступом

Теория

Управление доступом определяет, кто может выполнять какие операции.

Основные привилегии

Привилегия

Описание

SELECT

Чтение данных

INSERT

Добавление данных

UPDATE

Обновление данных

DELETE

Удаление данных

CREATE

Создание объектов

DROP

Удаление объектов

ALTER

Изменение структуры

EXECUTE

Выполнение функций

Примеры

-- Создание пользователя
CREATE USER analyst WITH PASSWORD 'secure_password';

-- Предоставление прав на чтение
GRANT SELECT ON ALL TABLES IN SCHEMA public TO analyst;

-- Предоставление прав на конкретные таблицы
GRANT SELECT, INSERT, UPDATE ON orders, order_details TO analyst;

-- Запрет на удаление
REVOKE DELETE ON orders FROM analyst;

-- Роли
CREATE ROLE data_analyst;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO data_analyst;
GRANT data_analyst TO analyst;

15. Распространенные ошибки на собеседовании

Ошибка

Правильно

Использование = с NULL

IS NULL

Агрегация без GROUP BY

SELECT category_id, COUNT(*) ... GROUP BY category_id

Фильтрация агрегатов в WHERE

Использовать HAVING

Сравнение разных типов

WHERE order_id = '123' (int vs varchar)

IN (SELECT ...) с NULL

NOT EXISTS безопаснее

Пропуск DISTINCT

COUNT(DISTINCT customer_id)


Шпаргалка для собеседования

Топ-10 запросов для практики

  1. Средний чек по клиентам

  2. Топ-10 продуктов по выручке

  3. Динамика продаж по месяцам

  4. RFM-анализ клиентов

  5. Когортный анализ удержания

  6. Скользящее среднее

  7. Сравнение с предыдущим периодом (LAG)

  8. Ранжирование внутри групп

  9. Процент от общего

  10. Иерархия сотрудников (рекурсивный CTE)

Ключевые концепции

  • INNER JOIN vs LEFT JOIN

  • WHERE vs HAVING

  • RANK() vs DENSE_RANK() vs ROW_NUMBER()

  • UNION vs UNION ALL

  • EXISTS vs IN

  • CTE vs подзапрос

  • Индексы и их влияние


Эта теория покрывает все необходимые темы для успешного прохождения собеседования на позицию Data Analyst. Удачи! 🚀