Загрузка…
Загрузка…
-- Single-line comment (standard)
/* Multi-line
comment */
# Hash comment (MySQL only)Когда вы запускаете
SELECT
, база данных не выполняет предложения в том порядке, в котором вы их записываете. Понимание логического порядка выполнения имеет решающее значение — оно объясняет, почему вы не можете ссылаться на псевдоним в WHERE, но можете в ORDER BY.
┌──────────────────────────────────────────────────────────────────┐
│ LOGICAL EXECUTION ORDER OF SELECT │
├────────┬─────────────────────────────────────────────────────────┤
│ 1 │ FROM + JOINs → Determine source tables │
│ 2 │ WHERE → Filter rows │
│ 3 │ GROUP BY → Aggregate into buckets │
│ 4 │ HAVING → Filter groups │
│ 5 │ SELECT → Compute columns & aliases │
│ 6 │ DISTINCT → Remove duplicates │
│ 7 │ ORDER BY → Sort results │
│ 8 │ LIMIT / OFFSET → Paginate │
└────────┴─────────────────────────────────────────────────────────┘Вот почему это не удается:
-- ❌ ERROR: alias "full_name" doesn't exist yet at step 2 (WHERE)
SELECT first_name || ' ' || last_name AS full_name
FROM employees
WHERE full_name = 'John Doe';
-- ✅ FIX: Repeat the expression or use a subquery/CTE
SELECT first_name || ' ' || last_name AS full_name
FROM employees
WHERE first_name || ' ' || last_name = 'John Doe';-- Comparison operators
WHERE salary > 50000
WHERE age BETWEEN 18 AND 65 -- Inclusive on both ends
WHERE department IN ('Engineering', 'Product', 'Design')
WHERE name LIKE 'A%' -- Starts with A
WHERE name LIKE '%son' -- Ends with son
WHERE name LIKE '_a%' -- Second letter is 'a'
WHERE name LIKE '%\_%' ESCAPE '\' -- Contains literal underscore
WHERE email IS NULL -- Missing email (NOT = NULL!)
WHERE email IS NOT NULLНУЛЕВАЯ Ловушка:
-- 🚨 WRONG: This returns NOTHING, not even rows where manager_id IS NULL
SELECT * FROM employees WHERE manager_id = NULL;
-- ✅ CORRECT:
SELECT * FROM employees WHERE manager_id IS NULL;
-- COALESCE gives you a fallback value:
SELECT name, COALESCE(phone, 'No phone') AS contact FROM users;
-- IFNULL is MySQL-specific; COALESCE is standard and accepts multiple args:
SELECT COALESCE(mobile, home_phone, work_phone, 'No phone') FROM contacts;-- Multi-column sort
SELECT * FROM products
ORDER BY category ASC, price DESC;
-- Pagination (Page 3, 20 items per page)
-- MySQL / PostgreSQL
SELECT * FROM products ORDER BY id LIMIT 20 OFFSET 40;
-- SQL Server
SELECT * FROM products ORDER BY id OFFSET 40 ROWS FETCH NEXT 20 ROWS ONLY;
-- Offset gets slower as page number grows!
-- For large tables, use keyset pagination:
SELECT * FROM products WHERE id > 1000 ORDER BY id LIMIT 20;Агрегатные функции сжимают несколько строк в одно итоговое значение:
| Функция | Цель | Обработка NULL |
|---|---|---|
COUNT(*)
| Посчитать все строки | Также считает NULL | |
COUNT(col)
| Подсчет значений, отличных от NULL | Игнорирует NULL | |
SUM(col)
| Всего | Игнорирует NULL | |
AVG(col)
| Средний | Игнорирует NULL | |
MIN(col)
/
MAX(col)
| Самый маленький/самый большой | Игнорирует NULL | |
GROUP_CONCAT()
/
STRING_AGG()
| Объединить строки | Зависит от БД |
-- Find departments with average salary > 60k, sorted
SELECT
department,
COUNT(*) AS headcount,
AVG(salary) AS avg_salary,
MAX(salary) AS top_salary
FROM employees
WHERE hire_date >= '2020-01-01' -- Filter ROWS first
GROUP BY department
HAVING AVG(salary) > 60000 -- Filter GROUPS after aggregation
ORDER BY avg_salary DESC;ГДЕ и ИМЕЕТ — критическая разница:
┌─────────────────────────────────────────────────────────────────┐
│ WHERE filters ROWS (before grouping) │
│ HAVING filters GROUPS (after aggregation) │
├─────────────────────────────────────────────────────────────────┤
│ │
│ Raw Rows → [WHERE] → Filtered Rows → [GROUP BY] → Groups │
│ ↓ │
│ Result ← [SELECT] ← [HAVING] ← Filtered Groups │
│ │
└─────────────────────────────────────────────────────────────────┘Ключевой вывод для собеседования: какие комментарии SQL являются действительными?
