90+ вопросов и ответов для собеседования по SQL (ENG)
Почти все крупные представители технологической индустрии, такие как Uber, Netflix, Airbnb и т.д., используют SQL. В этом блоге перечислены все лучшие вопросы для собеседования по SQL.
https://intellipaat.com/blog/interview-question/sql-interview-questions/
#SQL
👉 @database_info
Почти все крупные представители технологической индустрии, такие как Uber, Netflix, Airbnb и т.д., используют SQL. В этом блоге перечислены все лучшие вопросы для собеседования по SQL.
https://intellipaat.com/blog/interview-question/sql-interview-questions/
#SQL
👉 @database_info
👍4
This media is not supported in your browser
VIEW IN TELEGRAM
О командах SQL в двух словах
DDL (Data Definition Language): Занимается структурой или схемой базы данных.
CREATE: используется для создания таких объектов, как таблицы, представления, индексы и т. д.
ALTER: используется для изменения существующих объектов базы данных. Например, она может добавлять, удалять или изменять столбцы в существующей таблице.
DROP: используется для удаления объектов базы данных. Например, DROP TABLE удаляет существующую таблицу.
TRUNCATE: используется для удаления всех записей из таблицы, включая все места, отведенные для записей.
DML (Data Manipulation Language): Занимается манипулированием данными и управлением ими в базе данных.
INSERT: добавляет новые строки/записи в таблицу.
UPDATE: изменение существующих строк/записей в таблице.
DELETE: удаление строк/записей из таблицы.
MERGE: используется для вставки, обновления или удаления записей из таблицы на основе определенных условий.
DQL (Data Query Language): Используется для получения данных из базы данных.
SELECT: Извлекает данные из одной или нескольких таблиц. Эту команду можно комбинировать с различными предложениями (например, WHERE, GROUP BY, HAVING) для фильтрации, группировки и сортировки полученных данных.
DCL (Data Control Language): Имеет дело с разрешениями и правами, которые могут быть предоставлены или отменены.
GRANT: Предоставляет определенные привилегии пользователям или ролям.
REVOKE: отменяет определенные привилегии у пользователей или ролей.
TCL (Transaction Control Language): Используется для управления транзакциями в базе данных, обеспечивая целостность данных.
COMMIT: Сохраняет все транзакции в базе данных с момента последней команды COMMIT или ROLLBACK.
ROLLBACK: восстанавливает базу данных до состояния последней фиксации. При этом отменяются все изменения, сделанные с момента последнего COMMIT.
SAVEPOINT: устанавливает точку в транзакции, к которой впоследствии можно вернуться.
SET TRANSACTION: настройка свойств транзакции.
#SQL
👉 @database_info
DDL (Data Definition Language): Занимается структурой или схемой базы данных.
CREATE: используется для создания таких объектов, как таблицы, представления, индексы и т. д.
ALTER: используется для изменения существующих объектов базы данных. Например, она может добавлять, удалять или изменять столбцы в существующей таблице.
DROP: используется для удаления объектов базы данных. Например, DROP TABLE удаляет существующую таблицу.
TRUNCATE: используется для удаления всех записей из таблицы, включая все места, отведенные для записей.
DML (Data Manipulation Language): Занимается манипулированием данными и управлением ими в базе данных.
INSERT: добавляет новые строки/записи в таблицу.
UPDATE: изменение существующих строк/записей в таблице.
DELETE: удаление строк/записей из таблицы.
MERGE: используется для вставки, обновления или удаления записей из таблицы на основе определенных условий.
DQL (Data Query Language): Используется для получения данных из базы данных.
SELECT: Извлекает данные из одной или нескольких таблиц. Эту команду можно комбинировать с различными предложениями (например, WHERE, GROUP BY, HAVING) для фильтрации, группировки и сортировки полученных данных.
DCL (Data Control Language): Имеет дело с разрешениями и правами, которые могут быть предоставлены или отменены.
GRANT: Предоставляет определенные привилегии пользователям или ролям.
REVOKE: отменяет определенные привилегии у пользователей или ролей.
TCL (Transaction Control Language): Используется для управления транзакциями в базе данных, обеспечивая целостность данных.
COMMIT: Сохраняет все транзакции в базе данных с момента последней команды COMMIT или ROLLBACK.
ROLLBACK: восстанавливает базу данных до состояния последней фиксации. При этом отменяются все изменения, сделанные с момента последнего COMMIT.
SAVEPOINT: устанавливает точку в транзакции, к которой впоследствии можно вернуться.
SET TRANSACTION: настройка свойств транзакции.
#SQL
👉 @database_info
👍15
Документация YDB
YDB — это распределённая отказоустойчивая Distributed SQL СУБД. YDB обеспечивает высокую доступность, горизонтальную масштабируемость, а также строгую консистентность и поддержку ACID-транзакций. Для запросов используется диалект SQL (YQL).
https://ydb.tech/docs/ru/
#SQL
👉 @database_info
YDB — это распределённая отказоустойчивая Distributed SQL СУБД. YDB обеспечивает высокую доступность, горизонтальную масштабируемость, а также строгую консистентность и поддержку ACID-транзакций. Для запросов используется диалект SQL (YQL).
https://ydb.tech/docs/ru/
#SQL
👉 @database_info
👍3
Media is too big
VIEW IN TELEGRAM
Базы данных SQL уроки для начинающих. SELECT, JOINS, GROUP BY, INSERT, UPDATE, WHERE
00:00 - План на урок
00:50 - Виды баз данных
02:53 - О реляционных БД
03:15 - 1 нормальная форма
03:45 - 2 нормальная форма
04:50 - Связи между таблицами
06:12 - Начало работы с MySQL
06:47 - SHOW DATABASES
07:00 - CREATE DATABASE
07:16 - DROP DATABASE
07:40 - SHOW TABLES
07:55 - CREATE TABLE
08:50 - SHOW COLUMNS
10:10 - INSERT INTO
10:45 - SELECT *
11:15 - SELECT id, surname
11:40 - DISTINCT
12:10 - WHERE
12:45 - LIMIT
13:07 - AS
13:30 - ORDER BY
14:04 - ALTER TABLE
14:40 - UPDATE SET
15:30 - LIKE
16:20 - where AND OR
17:25 - BETWEEN
17:45 - DELETE
18:10 - Multiple INSERT
19:10 - Объединение таблиц \ JOINS
20:05 - INNER JOIN
21:00 - LEFT OUTER JOIN
21:15 - RIGHT OUTER JOIN
21:30 - UNION
22:04 - Агрегатные функции
23:10 - GROUP BY
#sql
👉 @database_info
00:00 - План на урок
00:50 - Виды баз данных
02:53 - О реляционных БД
03:15 - 1 нормальная форма
03:45 - 2 нормальная форма
04:50 - Связи между таблицами
06:12 - Начало работы с MySQL
06:47 - SHOW DATABASES
07:00 - CREATE DATABASE
07:16 - DROP DATABASE
07:40 - SHOW TABLES
07:55 - CREATE TABLE
08:50 - SHOW COLUMNS
10:10 - INSERT INTO
10:45 - SELECT *
11:15 - SELECT id, surname
11:40 - DISTINCT
12:10 - WHERE
12:45 - LIMIT
13:07 - AS
13:30 - ORDER BY
14:04 - ALTER TABLE
14:40 - UPDATE SET
15:30 - LIKE
16:20 - where AND OR
17:25 - BETWEEN
17:45 - DELETE
18:10 - Multiple INSERT
19:10 - Объединение таблиц \ JOINS
20:05 - INNER JOIN
21:00 - LEFT OUTER JOIN
21:15 - RIGHT OUTER JOIN
21:30 - UNION
22:04 - Агрегатные функции
23:10 - GROUP BY
#sql
👉 @database_info
👍8🔥2
Хранимые процедуры в SQL
В этой статье разберемся с хранимыми процедурами. Напомню, что мы работаем в СУБД MySQL, если вы работаете в другой СУБД, то некоторые синтаксические конструкции могут отличаться, но суть остается такой же.
https://telegra.ph/Hranimye-procedury-v-SQL-04-16
#SQL
👉 @database_info
В этой статье разберемся с хранимыми процедурами. Напомню, что мы работаем в СУБД MySQL, если вы работаете в другой СУБД, то некоторые синтаксические конструкции могут отличаться, но суть остается такой же.
https://telegra.ph/Hranimye-procedury-v-SQL-04-16
#SQL
👉 @database_info
Telegraph
Хранимые процедуры в SQL
В этой статье разберемся с хранимыми процедурами. Напомню, что мы работаем в СУБД MySQL, если вы работаете в другой СУБД, то некоторые синтаксические конструкции могут отличаться, но суть остается такой же. Общие сведения Итак, хранимые процедуры в SQL —…
👍3👎1🔥1
Представления в SQL
Здравствуйте, в этой статье будут разобраны представления или view в SQL. На простых примерах объясним как создавать представления и как к ним обращаться. Также затронем понятие модифицируемого представления в SQL.
https://telegra.ph/Predstavleniya-v-SQL-06-18
#SQL
👉 @database_info
Здравствуйте, в этой статье будут разобраны представления или view в SQL. На простых примерах объясним как создавать представления и как к ним обращаться. Также затронем понятие модифицируемого представления в SQL.
https://telegra.ph/Predstavleniya-v-SQL-06-18
#SQL
👉 @database_info
❤5👍2👎1
Самоучитель по SQL
Наш самоучитель по SQL научит вас использовать SQL в: MySQL, SQL Server, MS Access, Oracle, Sybase, Informix, Postgres и других системах баз данных.
https://www.w3schools.com/sql/default.asp
#db #sql
👉 @database_info
Наш самоучитель по SQL научит вас использовать SQL в: MySQL, SQL Server, MS Access, Oracle, Sybase, Informix, Postgres и других системах баз данных.
https://www.w3schools.com/sql/default.asp
#db #sql
👉 @database_info
👍4😁1
This media is not supported in your browser
VIEW IN TELEGRAM
Получение значений из строк N до/после текущей строки с помощью 2-го параметра LAG/LEAD
например.
За пределами first/last row => возвращаем
Используйте 3-й параметр, чтобы вернуть значение по умолчанию
#db #sql
👉 @database_info
например.
LAG ( ..., 2 ) OVER ( ORDER BY ... ) = 2 before
LEAD ( ..., 3 ) OVER ( ORDER BY ... ) = 3 afterЗа пределами first/last row => возвращаем
nullИспользуйте 3-й параметр, чтобы вернуть значение по умолчанию
#db #sql
👉 @database_info
👍5🥰2
Находим первое, N-ое или последнее значение в SQL
Условие
Будьте осторожны с использованием значения по умолчанию - оно останавливает
#db #sql
👉 @database_info
FIRST_VALUE ( val ) - Start val
NTH_VALUE ( val, N ) - Val at row N
LAST_VALUE ( val ) - Final valУсловие
OVER определяет порядокБудьте осторожны с использованием значения по умолчанию - оно останавливает
NTH и LAST на текущем значении => неожиданные результаты#db #sql
👉 @database_info
👍4🥰3❤2
Media is too big
VIEW IN TELEGRAM
Практические примеры по оптимизации запросов в PostgeSQL
Иван Чувашов
источник
#db #sql #postgesql
👉 @database_info
Иван Чувашов
источник
#db #sql #postgesql
👉 @database_info
👍4
Media is too big
VIEW IN TELEGRAM
SQL injection - почему, зачем и как защититься от SQL инъекции
В этом видио хотелось бы поговорить про очень опасную на мой взгляд хакерскую атаку SQL Injection. Это одна из старейших атак и она все ещё актуальна. Сегодня мы рассмотрим примеры использования SQL Injection на примере небольшого C# приложения. В других языках программирования и фреймворках все работает идентично.
источник
#sql
👉 @database_info
В этом видио хотелось бы поговорить про очень опасную на мой взгляд хакерскую атаку SQL Injection. Это одна из старейших атак и она все ещё актуальна. Сегодня мы рассмотрим примеры использования SQL Injection на примере небольшого C# приложения. В других языках программирования и фреймворках все работает идентично.
источник
#sql
👉 @database_info
👍3
Media is too big
VIEW IN TELEGRAM
SQL Injection - теория и примеры
В прошлом видео я поспешил рассказать и показать SQL Injection на практике, а в этом видео я хочу сделать шаг назад и поговорить чуть больше о теории и больше рассмотреть небольших примеров.
источник
#sql
👉 @database_info
В прошлом видео я поспешил рассказать и показать SQL Injection на практике, а в этом видео я хочу сделать шаг назад и поговорить чуть больше о теории и больше рассмотреть небольших примеров.
источник
#sql
👉 @database_info
👍5
Как найти дубли в sql
Для того чтобы найти дубликаты в базе данных SQL, можно использовать операторы
Этот запрос выведет все уникальные значения столбца "столбец", а также количество раз, которое каждое значение повторяется в таблице. Результатом будут только те строки, где значение столбца повторяется более одного раза, что указывает на наличие дубликатов.
Также можно использовать операторы JOIN или подзапросы для более сложных запросов на поиск дубликатов. Важно помнить, что перед выполнением подобных операций на поиск дубликатов необходимо создать резервную копию базы данных или таблицы, чтобы избежать потери данных.
#sql
👉 @database_info
Для того чтобы найти дубликаты в базе данных SQL, можно использовать операторы
SELECT и GROUP BY совместно с оператором HAVING. Например, следующий запрос позволяет найти все строки, у которых значение определенного столбца повторяется более одного раза:
SELECT столбец, COUNT(*) AS количество
FROM таблица
GROUP BY столбец
HAVING COUNT(*) > 1;
Этот запрос выведет все уникальные значения столбца "столбец", а также количество раз, которое каждое значение повторяется в таблице. Результатом будут только те строки, где значение столбца повторяется более одного раза, что указывает на наличие дубликатов.
Также можно использовать операторы JOIN или подзапросы для более сложных запросов на поиск дубликатов. Важно помнить, что перед выполнением подобных операций на поиск дубликатов необходимо создать резервную копию базы данных или таблицы, чтобы избежать потери данных.
#sql
👉 @database_info
👍3
Совет по работе с базой данных💡
Дубликаты строк легко создаются по ошибке и почти так же легко удаляются: вы можете в *одном* SQL-запросе определить их, а также указать, какой из них оставить!
Вот самый быстрый способ 👆
#sql
👉 @database_info
Дубликаты строк легко создаются по ошибке и почти так же легко удаляются: вы можете в *одном* SQL-запросе определить их, а также указать, какой из них оставить!
Вот самый быстрый способ 👆
#sql
👉 @database_info
👍3
Писать чистый SQL проще с pgx и sqlc в Go
Что такое pgx и sqlc?
pgx: это надежный набор инструментов и драйвер для PostgreSQL в Golang. Этот модуль также предоставляет полезные инструменты для облегчения работы со сложными запросами, делая их менее подверженными ошибкам.
sqlc: это инструмент для генерации кода, который преобразует ваши SQL-запросы в файлах .sql в Go-код с типобезопасностью как для параметров запроса, так и для результатов. Пример можно посмотреть здесь: sqlc playground. sqlc также поддерживает pgx "из коробки", что делает эту комбинацию отличным решением для работы с базами данных.
https://remvn.dev/posts/writing-raw-sql-easier-with-pgx-and-sqlc-in-go/
#sql
👉 @database_info
Что такое pgx и sqlc?
pgx: это надежный набор инструментов и драйвер для PostgreSQL в Golang. Этот модуль также предоставляет полезные инструменты для облегчения работы со сложными запросами, делая их менее подверженными ошибкам.
sqlc: это инструмент для генерации кода, который преобразует ваши SQL-запросы в файлах .sql в Go-код с типобезопасностью как для параметров запроса, так и для результатов. Пример можно посмотреть здесь: sqlc playground. sqlc также поддерживает pgx "из коробки", что делает эту комбинацию отличным решением для работы с базами данных.
https://remvn.dev/posts/writing-raw-sql-easier-with-pgx-and-sqlc-in-go/
#sql
👉 @database_info
👍2
Курс по SQLAlchemy. Часть 1
Зачем Учить SQLAlchemy ORM
Подключение к Базе Данных, сырые SQL запросы через engine #2
Создание таблиц и вставка данных через Core #3
Session и первые шаги в ORM #4
Создание таблиц через КЛАССЫ - Mapped и mapped_column #5
SELECT и UPDATE запросы через ORM и Core #6
Базовые SELECT запросы #7
источник
#SQL
👉 @database_info
Зачем Учить SQLAlchemy ORM
Подключение к Базе Данных, сырые SQL запросы через engine #2
Создание таблиц и вставка данных через Core #3
Session и первые шаги в ORM #4
Создание таблиц через КЛАССЫ - Mapped и mapped_column #5
SELECT и UPDATE запросы через ORM и Core #6
Базовые SELECT запросы #7
источник
#SQL
👉 @database_info
👍9🔥1
SQL: Бесплатные курсы
Курсы на русском языке:
Интерактивный тренажер по SQL
Введение в базы данных
SQLite на практике
Базы данных
SQL Учебник
Курсы на английском языке:
Khan Academy
SQL for Data Science (IBM)
SQL Tutorial (SQL ZOO)
Intro to SQL (Kaggle)
Advanced SQL (Kaggle)
Lern SQL (Codeacademy)
SQL for Data Science (UCDavice, University of California)
#SQL
👉 @database_info
Курсы на русском языке:
Интерактивный тренажер по SQL
Введение в базы данных
SQLite на практике
Базы данных
SQL Учебник
Курсы на английском языке:
Khan Academy
SQL for Data Science (IBM)
SQL Tutorial (SQL ZOO)
Intro to SQL (Kaggle)
Advanced SQL (Kaggle)
Lern SQL (Codeacademy)
SQL for Data Science (UCDavice, University of California)
#SQL
👉 @database_info
❤8
Антипаттерн: N+1 запросов — как заметить и починить
Вы берёте список сущностей, а потом в цикле для каждой тянете связанные данные. В итоге - 1 запрос за «родителями» + N запросов за «детьми». Латентность растёт линейно от размера выборки.
Симптомы
- В логах много одинаковых коротких запросов.
- Кол-во запросов ≈ размеру списка.
- Страница/endpoint сильно «замедляется» при росте данных.
Плохой пример (SQL + псевдокод)
Правильно (SQL, PostgreSQL) — сетевое мышление:
Django ORM
SQLAlchemy
Практические советы
- Логируйте кол-во запросов на эндпойнт/страницу. В Django - django-debug-toolbar, assertNumQueries в тестах; в SQLAlchemy - echo/интеграция с логгером.
- Индексы: обязательно
- Батчинг вместо циклов: тяните детей одним запросом
- Осторожно с joinedload для 1:N на больших выборках - риск «взрыва» строк. Для 1:N чаще выбирайте selectinload.
- Колонки по делу: не тащите
- Пагинация: уменьшает N и давление на сеть/память.
- EXPLAIN (ANALYZE, BUFFERS) - проверяйте планы и кардинальности.
💡Думайте наборами, а не циклами. Eager loading + агрегаты закрывают 90% случаев N+1. Настройте мониторинг количества запросов - и ловите проблему до продакшена.
Сохрани, чтобы не наступить снова. Поделись с коллегами. А как вы ловите N+1 у себя?
#SQL
👉 @database_info
Вы берёте список сущностей, а потом в цикле для каждой тянете связанные данные. В итоге - 1 запрос за «родителями» + N запросов за «детьми». Латентность растёт линейно от размера выборки.
Симптомы
- В логах много одинаковых коротких запросов.
- Кол-во запросов ≈ размеру списка.
- Страница/endpoint сильно «замедляется» при росте данных.
Плохой пример (SQL + псевдокод)
-- Берём пользователей
SELECT id, name FROM users WHERE active = true;
-- Потом в цикле по каждому:
SELECT count(*) FROM orders WHERE user_id = :id;
Правильно (SQL, PostgreSQL) — сетевое мышление:
SELECT u.id,
u.name,
count(o.*) AS orders_cnt
FROM users u
LEFT JOIN orders o ON o.user_id = u.id
WHERE u.active = true
GROUP BY u.id, u.name;
Django ORM
# Плохо: в шаблоне/цикле обращаемся к user.orders -> N+1
users = User.objects.filter(active=True)
# Хорошо: подгрузим связи заранее
users = (User.objects
.filter(active=True)
.prefetch_related('orders')) # для 1:N
# для 1:1 / ForeignKey используйте select_related('profile')
# Агрегация без цикла
from django.db.models import Count
users = (User.objects.filter(active=True)
.annotate(orders_cnt=Count('orders')))
SQLAlchemy
from sqlalchemy.orm import selectinload, joinedload
# 1:N — безопаснее selectinload (батчирует IN (...))
users = (session.query(User)
.options(selectinload(User.orders))
.filter(User.active.is_(True))
.all())
# 1:1 — joinedload
user = (session.query(User)
.options(joinedload(User.profile))
.get(user_id))
Практические советы
- Логируйте кол-во запросов на эндпойнт/страницу. В Django - django-debug-toolbar, assertNumQueries в тестах; в SQLAlchemy - echo/интеграция с логгером.
- Индексы: обязательно
orders(user_id); если фильтруете по статусу - составной (user_id, status).- Батчинг вместо циклов: тяните детей одним запросом
WHERE user_id IN (...), затем мапьте в памяти.- Осторожно с joinedload для 1:N на больших выборках - риск «взрыва» строк. Для 1:N чаще выбирайте selectinload.
- Колонки по делу: не тащите
SELECT *, берите только нужные поля.- Пагинация: уменьшает N и давление на сеть/память.
- EXPLAIN (ANALYZE, BUFFERS) - проверяйте планы и кардинальности.
💡Думайте наборами, а не циклами. Eager loading + агрегаты закрывают 90% случаев N+1. Настройте мониторинг количества запросов - и ловите проблему до продакшена.
Сохрани, чтобы не наступить снова. Поделись с коллегами. А как вы ловите N+1 у себя?
#SQL
👉 @database_info
👍8❤3
Типы JOIN в SQL и когда их применять
- INNER JOIN - пересечение множеств (только совпавшие строки).
- LEFT JOIN - все слева + совпавшие справа (несовпавшие →
- RIGHT JOIN - симметричен LEFT, лучше переворачивать под LEFT.
- FULL OUTER JOIN - все слева и справа (где нет пары →
- CROSS JOIN — декартово произведение (каждая со всеми).
- SELF JOIN - таблица соединяется сама с собой.
- SEMI / ANTI JOIN - “есть/нет соответствия” (через
- LATERAL / APPLY - зависимая подзапросная таблица на строку слева.
1️⃣ INNER JOIN - «строго есть пара»
«Покажи оплаченные заказы с данными клиента».
Используйте, когда отсутствие пары - повод исключить строку.
2️⃣ LEFT JOIN - «все слева, даже без пары»
«Список клиентов и количество их заказов (включая с нулём)».
По умолчанию для «обогащения» справочниками и опциональных связей.
3️⃣ RIGHT JOIN - почти не нужен
Заменяйте на LEFT, поменяв стороны:
4️⃣ FULL OUTER JOIN - «объединить всё»
«Свод по всем клиентам и всем заказам, даже если без пары».
Редко нужен в отчётах/сверках. Поддержка зависит от СУБД.
5️⃣ CROSS JOIN - «все комбинации»
«Собрать сетку метрик по всем регионам и кварталам».
Осторожно: взрыв строк.
6️⃣ SELF JOIN - «сравнить строки внутри таблицы»
«Найти менеджера и его подчинённого».
7️⃣ SEMI JOIN (EXISTS) - «фильтрация по факту наличия»
«Клиенты, у кого были заказы за 30 дней».
Не размножает строки, часто быстрее, чем
8️⃣ ANTI JOIN (NOT EXISTS) - «кто без соответствий»
«Товары, которые ни разу не покупали в этом году».
Избегайте
9️⃣ LATERAL / APPLY - «топ-N на строку»
«Последний заказ на клиента» (PostgreSQL:
💡 Подводные камни
- LEFT JOIN + фильтр в WHERE ⇒ превращается в INNER.
Если нужно оставить «без пары», переносите условие в
- Дубликаты из «один-ко-многим». Перед JOIN делайте агрегацию в подзапросе/CTE.
- Индексы на ключах соединений (FK и соответствующие PK/UK) - must.
- Сопоставимость типов/колляций. Функции на ключе (
-
- Проверяйте план.
Сохрани, чтобы не забыть. А как вы чаще фильтруете - через JOIN+DISTINCT или EXISTS?
#SQL
👉 @database_info
- INNER JOIN - пересечение множеств (только совпавшие строки).
- LEFT JOIN - все слева + совпавшие справа (несовпавшие →
NULL).- RIGHT JOIN - симметричен LEFT, лучше переворачивать под LEFT.
- FULL OUTER JOIN - все слева и справа (где нет пары →
NULL).- CROSS JOIN — декартово произведение (каждая со всеми).
- SELF JOIN - таблица соединяется сама с собой.
- SEMI / ANTI JOIN - “есть/нет соответствия” (через
EXISTS / NOT EXISTS).- LATERAL / APPLY - зависимая подзапросная таблица на строку слева.
1️⃣ INNER JOIN - «строго есть пара»
«Покажи оплаченные заказы с данными клиента».
SELECT o.id, c.name
FROM orders o
JOIN customers c ON c.id = o.customer_id
WHERE o.status = 'paid';
Используйте, когда отсутствие пары - повод исключить строку.
2️⃣ LEFT JOIN - «все слева, даже без пары»
«Список клиентов и количество их заказов (включая с нулём)».
SELECT c.id, c.name, COALESCE(COUNT(o.id), 0) AS orders_cnt
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.id
GROUP BY c.id, c.name;
По умолчанию для «обогащения» справочниками и опциональных связей.
3️⃣ RIGHT JOIN - почти не нужен
Заменяйте на LEFT, поменяв стороны:
-- было:
-- SELECT ... FROM A RIGHT JOIN B ON ...
-- стало:
SELECT ...
FROM B
LEFT JOIN A ON ...
4️⃣ FULL OUTER JOIN - «объединить всё»
«Свод по всем клиентам и всем заказам, даже если без пары».
SELECT COALESCE(c.id, o.customer_id) AS customer_key, c.name, o.id AS order_id
FROM customers c
FULL JOIN orders o ON o.customer_id = c.id;
Редко нужен в отчётах/сверках. Поддержка зависит от СУБД.
5️⃣ CROSS JOIN - «все комбинации»
«Собрать сетку метрик по всем регионам и кварталам».
SELECT r.region, q.quarter
FROM regions r
CROSS JOIN quarters q;
Осторожно: взрыв строк.
6️⃣ SELF JOIN - «сравнить строки внутри таблицы»
«Найти менеджера и его подчинённого».
SELECT e.name AS employee, m.name AS manager
FROM employees e
LEFT JOIN employees m ON m.id = e.manager_id;
7️⃣ SEMI JOIN (EXISTS) - «фильтрация по факту наличия»
«Клиенты, у кого были заказы за 30 дней».
SELECT c.*
FROM customers c
WHERE EXISTS (
SELECT 1 FROM orders o
WHERE o.customer_id = c.id
AND o.created_at >= CURRENT_DATE - INTERVAL '30 day'
);
Не размножает строки, часто быстрее, чем
JOIN + DISTINCT.8️⃣ ANTI JOIN (NOT EXISTS) - «кто без соответствий»
«Товары, которые ни разу не покупали в этом году».
SELECT p.*
FROM products p
WHERE NOT EXISTS (
SELECT 1 FROM order_items oi
JOIN orders o ON o.id = oi.order_id
WHERE oi.product_id = p.id
AND o.created_at >= date_trunc('year', CURRENT_DATE)
);
Избегайте
NOT IN с NULL - может дать пустой результат.9️⃣ LATERAL / APPLY - «топ-N на строку»
«Последний заказ на клиента» (PostgreSQL:
LATERAL, SQL Server: APPLY).
SELECT c.id, c.name, o_last.id AS last_order_id
FROM customers c
LEFT JOIN LATERAL (
SELECT o.id
FROM orders o
WHERE o.customer_id = c.id
ORDER BY o.created_at DESC
LIMIT 1
) o_last ON true;
- LEFT JOIN + фильтр в WHERE ⇒ превращается в INNER.
Если нужно оставить «без пары», переносите условие в
ON:
-- ❌ неверно
SELECT ... FROM c LEFT JOIN o ON o.customer_id = c.id
WHERE o.status = 'paid';
-- ✅ верно
SELECT ... FROM c LEFT JOIN o
ON o.customer_id = c.id AND o.status = 'paid';
- Дубликаты из «один-ко-многим». Перед JOIN делайте агрегацию в подзапросе/CTE.
- Индексы на ключах соединений (FK и соответствующие PK/UK) - must.
- Сопоставимость типов/колляций. Функции на ключе (
LOWER(col)) ломают sargability - лучше нормализовать данные заранее.-
EXISTS чаще лучше, чем JOIN + DISTINCT для фильтрации.- Проверяйте план.
EXPLAIN (ANALYZE, BUFFERS) и сравнение альтернатив.Сохрани, чтобы не забыть. А как вы чаще фильтруете - через JOIN+DISTINCT или EXISTS?
#SQL
👉 @database_info
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7🔥4❤1