SELECT
Базовый SELECT
SELECT name, age FROM users WHERE age > 18 ORDER BY age DESC LIMIT 10 OFFSET 20;
SELECT DISTINCT department FROM employees;
Агрегация
SELECT department, COUNT(*), AVG(salary), MAX(salary), MIN(salary), SUM(bonus)
FROM employees
GROUP BY department
HAVING COUNT(*) > 5
ORDER BY AVG(salary) DESC;
JOIN
Поддерживается INNER JOIN на N таблиц; LEFT/RIGHT/FULL OUTER JOIN — только для двух таблиц.
SELECT u.name, p.title, c.body
FROM users u
INNER JOIN posts p ON u.id = p.author_id
INNER JOIN comments c ON p.id = c.post_id;
Subquery
SELECT * FROM users WHERE id IN (SELECT user_id FROM admins);
Коррелированные EXISTS/scalar subquery тоже поддерживаются и автоматически декоррелируются планировщиком там, где это возможно (заметный прирост производительности на больших выборках).
Window functions
Поддерживаются: ROW_NUMBER, RANK, DENSE_RANK, NTILE, LAG, LEAD, FIRST_VALUE, LAST_VALUE, а также агрегаты (SUM/AVG/COUNT/MIN/MAX) в качестве оконных функций — с PARTITION BY, ORDER BY и явными ROWS BETWEEN ... AND ... фреймами; окно можно ставить поверх обычного SELECT, поверх JOIN и поверх GROUP BY.
SELECT department, name, salary,
RANK() OVER (PARTITION BY department ORDER BY salary DESC) AS rnk
FROM employees;
Не поддерживается: RANGE с числовым offset (нужна peer-group семантика) — только ROWS-фреймы.
CTE (WITH ...)
Поддерживаются: один или несколько CTE в запросе, JOIN CTE с CTE. Ограничения: CTE — некорректирующий (нет WITH RECURSIVE), тело CTE — только простой SELECT, CTE нельзя объединить более чем с одним JOIN за раз, и CTE не может ссылаться на другой CTE того же WITH.
WITH top_customers AS (
SELECT customer_id, SUM(amount) AS total
FROM orders
GROUP BY customer_id
)
SELECT c.name, t.total
FROM top_customers t
JOIN customers c ON c.id = t.customer_id
ORDER BY t.total DESC
LIMIT 10;