CREATE TABLE departments (
id SERIAL PRIMARY KEY,
name VARCHAR(100),
budget NUMERIC(12, 2)
);
CREATE TABLE employees (
id SERIAL PRIMARY KEY,
name VARCHAR(100),
department_id INT REFERENCES departments(id),
manager_id INT REFERENCES employees(id),
salary NUMERIC(10, 2),
hire_date DATE,
status VARCHAR(20) DEFAULT 'active'
);
CREATE TABLE orders (
id SERIAL PRIMARY KEY,
customer_id INT,
employee_id INT REFERENCES employees(id),
order_date TIMESTAMP DEFAULT NOW(),
amount NUMERIC(10, 2),
status VARCHAR(20)
);
CREATE TABLE products (
id SERIAL PRIMARY KEY,
name VARCHAR(100),
category VARCHAR(50),
price NUMERIC(10, 2),
stock INT
);
CREATE TABLE order_items (
id SERIAL PRIMARY KEY,
order_id INT REFERENCES orders(id),
product_id INT REFERENCES products(id),
quantity INT,
unit_price NUMERIC(10, 2)
); SELECT * FROM orders WHERE customer_id = 123 AND status = 'pending' ORDER BY order_date DESC; SELECT * FROM users WHERE LOWER(email) = 'test@example.com'; SELECT * FROM orders ORDER BY created_at DESC LIMIT 20 OFFSET 100000; EXPLAIN ANALYZE
SELECT * FROM orders WHERE customer_id = 123;
-- Результат:
-- Seq Scan on orders (cost=0.00..1520.00 rows=50) (actual time=0.020..15.432 rows=47 loops=1)
-- Filter: (customer_id = 123)
-- Rows Removed by Filter: 9953 EXPLAIN ANALYZE
SELECT customer_id, amount FROM orders WHERE customer_id = 123;
-- Index Scan using idx_orders_customer on orders
-- Heap Fetches: 47 -- Nested Loop (actual time=0.050..45000.000 rows=1000 loops=1)
-- -> Seq Scan on orders o (actual time=0.010..10.000 rows=1000 loops=1)
-- -> Index Scan on users u (actual time=0.040..44.000 rows=1 loops=1000) EXPLAIN (ANALYZE, BUFFERS)
SELECT * FROM orders ORDER BY amount DESC LIMIT 100;
-- Sort Method: external merge Disk: 15000kB EXPLAIN ANALYZE
SELECT * FROM orders WHERE status IN ('pending', 'processing', 'shipped');
-- Bitmap Heap Scan on orders
-- Recheck Cond: (status = ANY (...))
-- Heap Blocks: exact=2000
-- -> Bitmap Index Scan on idx_orders_status Задача | Ключевой приём |
Топ-N в группе | ROW_NUMBER() OVER (PARTITION BY ... ORDER BY ...) |
N-я по величине | DENSE_RANK() или OFFSET N-1 |
Накопительная сумма | SUM() OVER (ORDER BY ...) |
Сравнение с предыдущим | LAG() / LEAD() |
Процент от общего | COUNT() / SUM(COUNT()) OVER () |
Streak | date - ROW_NUMBER() группирует |
Функция в WHERE | Функциональный индекс |
Большой OFFSET | Keyset pagination |
LIKE '%text%' | pg_trgm + GIN |
Скользящее среднее | ROWS BETWEEN N PRECEDING (+ generate_series!) |
Заполнение пропусков | generate_series + LEFT JOIN |