SELECT * FROM users WHERE status = 'active'; SELECT * FROM users
WHERE age > 25 AND city = 'Москва'; SELECT * FROM products
WHERE price < 1000 OR price > 10000; SELECT * FROM users
WHERE email LIKE '%@gmail.com'; SELECT * FROM products
WHERE category IN ('Электроника', 'Одежда'); -- ПРАВИЛЬНО (работает с TIMESTAMP и DATE):
SELECT * FROM orders
WHERE order_date >= '2024-01-01' AND order_date < '2024-02-01'; -- НЕПРАВИЛЬНО использовать BETWEEN для дат с временем!
WHERE order_date BETWEEN '2024-01-01' AND '2024-01-31';
-- Пропустит записи 2024-01-31 01:00:00 и позже! SELECT * FROM products
WHERE stock BETWEEN 10 AND 100; SELECT * FROM products
ORDER BY price DESC
LIMIT 10; SELECT * FROM users
ORDER BY city, name; SELECT * FROM users WHERE status = 'active'; SELECT * FROM products
ORDER BY id
LIMIT 10 OFFSET 10; SELECT * FROM users
WHERE created_at::date = CURRENT_DATE; SELECT * FROM orders
WHERE order_date >= CURRENT_DATE - INTERVAL '7 days'; SELECT
id,
EXTRACT(YEAR FROM order_date) AS year,
EXTRACT(MONTH FROM order_date) AS month
FROM orders; SELECT
id,
order_date,
CURRENT_DATE - order_date AS days_ago
FROM orders; -- Извлечь первое слово (имя):
SELECT SPLIT_PART(name, ' ', 1) AS first_name FROM users;
-- Извлечь второе слово (фамилия):
SELECT SPLIT_PART(name, ' ', 2) AS last_name FROM users;
-- Оба вместе:
SELECT
SPLIT_PART(name, ' ', 1) AS first_name,
SPLIT_PART(name, ' ', 2) AS last_name
FROM users; SELECT LOWER(email) FROM users; SELECT name, LENGTH(name) AS name_length FROM users; SELECT * FROM users WHERE age IS NULL;
-- НЕПРАВИЛЬНО (никогда не работает!):
SELECT * FROM users WHERE age = NULL; -- Правильно:
SELECT * FROM users WHERE email IS NULL;
-- НЕПРАВИЛЬНО (никогда не работает!):
SELECT * FROM users WHERE email = NULL; SELECT
COUNT(*) AS total,
COUNT(email) AS with_email,
COUNT(*) - COUNT(email) AS without_email
FROM users; -- Для одного поля:
SELECT name, COALESCE(phone, 'Не указан') AS phone FROM users;
-- Для нескольких (первое не-NULL):
SELECT name, COALESCE(email, phone, 'Нет контакта') AS contact
FROM users;
-- Для чисел (в расчётах):
SELECT name, COALESCE(age, 0) AS age FROM users; -- Проблема: деление на 0
SELECT price / stock AS price_per_item FROM products; -- ERROR при stock = 0
-- Решение: NULLIF превращает 0 в NULL, а x / NULL = NULL
SELECT price / NULLIF(stock, 0) AS price_per_item FROM products;
-- С обработкой результата:
SELECT COALESCE(price / NULLIF(stock, 0), 0) AS price_per_item FROM products; -- ОПАСНО: если в orders есть user_id = NULL, вернёт 0 строк!
SELECT * FROM users
WHERE id NOT IN (SELECT user_id FROM orders);
-- БЕЗОПАСНО вариант 1: фильтровать NULL
SELECT * FROM users
WHERE id NOT IN (SELECT user_id FROM orders WHERE user_id IS NOT NULL);
-- БЕЗОПАСНО вариант 2: NOT EXISTS (рекомендуется)
SELECT * FROM users u
WHERE NOT EXISTS (SELECT 1 FROM orders o WHERE o.user_id = u.id); -- NULL в конец (при ASC):
SELECT * FROM users ORDER BY last_login NULLS LAST;
-- NULL в начало:
SELECT * FROM users ORDER BY last_login NULLS FIRST;
-- Альтернатива через COALESCE:
SELECT * FROM users ORDER BY COALESCE(last_login, '1970-01-01'); SELECT
name,
age,
CASE
WHEN age < 18 THEN 'Несовершеннолетний'
WHEN age BETWEEN 18 AND 25 THEN 'Молодой'
WHEN age BETWEEN 26 AND 45 THEN 'Взрослый'
WHEN age BETWEEN 46 AND 65 THEN 'Старший'
ELSE 'Пенсионер'
END AS age_group
FROM users; SELECT
id,
amount,
CASE status
WHEN 'pending' THEN 'Ожидает обработки'
WHEN 'completed' THEN 'Выполнен'
WHEN 'shipped' THEN 'Отправлен'
WHEN 'cancelled' THEN 'Отменён'
ELSE 'Неизвестный статус'
END AS status_text
FROM orders; SELECT
id,
amount,
CASE
WHEN amount >= 50000 THEN amount * 0.85 -- скидка 15%
WHEN amount >= 20000 THEN amount * 0.90 -- скидка 10%
WHEN amount >= 10000 THEN amount * 0.95 -- скидка 5%
ELSE amount
END AS discounted_amount
FROM orders; -- DELETE — удаляет строки по одной, можно откатить, триггеры срабатывают
DELETE FROM logs WHERE created_at < '2023-01-01';
-- TRUNCATE — мгновенно очищает всю таблицу
TRUNCATE TABLE logs;
-- В PostgreSQL TRUNCATE можно откатить внутри транзакции!
-- TRUNCATE сбрасывает счётчик SERIAL/IDENTITY:
TRUNCATE TABLE logs RESTART IDENTITY; Характеристика | DELETE | TRUNCATE |
Скорость | Медленно | Мгновенно |
WHERE | Да | Нет |
Триггеры | Да | Нет |
Откат | Да | Да (PostgreSQL) |
VACUUM нужен | Да | Нет |
-- UNION — убирает дубликаты (медленнее)
SELECT city FROM users
UNION
SELECT city FROM customers;
-- UNION ALL — оставляет дубликаты (быстрее)
SELECT city FROM users
UNION ALL
SELECT city FROM customers; SELECT
COUNT(*) AS total_rows, -- все строки (включая NULL)
COUNT(email) AS with_email, -- строки где email NOT NULL
COUNT(DISTINCT city) AS cities -- уникальные города (без NULL)
FROM users;
-- Пример:
-- COUNT(*) = 3
-- COUNT(email) = 2 (если один email = NULL)
-- COUNT(DISTINCT city) = 1 (если все из одного города) Задача | Ключевой приём |
Фильтрация | WHERE + условия |
Несколько значений | IN (...) |
Диапазон дат | >= AND < (НЕ BETWEEN для TIMESTAMP!) |
Шаблон | LIKE '%...%' |
Сортировка | ORDER BY ... DESC |
Ограничение | LIMIT N OFFSET M |
NULL | IS NULL, COALESCE |
Условная логика | CASE WHEN |