---
title: Соединения и запросы
seo:
  title: Соединения и запросы — Data Analyst
  description: Тема «Соединения и запросы» для собеседования Data Analyst. Что такое выражение GROUP BY и как оно используется? Что такое self-join и когда используется?
---

[Все темы Data Analyst](/data-analyst)

## <strong>Что такое выражение</strong> <code>GROUP BY</code> <strong>и как оно используется?</strong> [#q-14bee738d69b8182895cf866c85c9c5e]

Выражение <code>GROUP BY</code> – это оператор SQL, используемый для группировки строк с одинаковыми значениями в одном или нескольких столбцах в итоговые строки, например, “найти общий объем продаж для каждого продукта”.

GROUP BY группирует строки по указанным выражениям. Агрегатные функции часто используются вместе с ним, но не обязательны&#58; SELECT Product FROM Sales GROUP BY Product возвращает уникальные группы.

Например, если у вас есть таблица “<code>Sales</code>” (“Продажи”) со столбцами “<code>Product</code>” (“Продукт”), “<code>Date</code>” (“Дата”) и “<code>Sales Amount</code>” (“Сумма продаж”), и вы хотите найти общую сумму продаж для каждого продукта, вы можете использовать следующий SQL-запрос&#58;

```sql
SELECT Product, SUM([Sales Amount]) as TotalSales
FROM Sales
GROUP BY Product;
```

В результате будет получена таблица с двумя столбцами&#58; “<code>Product</code>” и “<code>TotalSales</code>”, где каждая строка представляет собой уникальный продукт и его общий объем продаж.

Оператор <code>GROUP BY</code> также можно использовать с несколькими столбцами, что позволит сгруппировать данные по каждой уникальной комбинации столбцов. Например&#58;

```sql
SELECT Product, Date, SUM([Sales Amount]) as TotalSales
FROM Sales
GROUP BY Product, Date;
```

В результате будет получена таблица с тремя столбцами&#58; “<code>Product</code>”, “<code>Date</code>” и “<code>TotalSales</code>”, где каждая строка представляет собой уникальную комбинацию продукта и даты, а также общее количество продаж.

:::note[Ссылки для изучения]

1. [Базовый синтаксис SQL](https://sql-academy.org/ru/guide/basic-syntax-sql-query)
   :::

---

## <strong>Что такое</strong> <code>self&#45;join</code> <strong>и когда используется?</strong> [#q-14bee738d69b8166b611f597aa2b54ef]

<code>Self&#45;join</code> в SQL – это тип операции соединения, при которой
таблица объединяется сама с собой. Это полезно, когда у вас есть таблица со
связанными данными в разных строках, которые вы хотите объединить на основе
общего поля.

Например, рассмотрим таблицу “<code>employees</code>” (“Сотрудники”) со столбцами для ID и имени сотрудника, а также ID менеджера. Столбец ID менеджера содержит ID менеджера сотрудника. Чтобы получить список всех сотрудников с именем их менеджера, можно использовать <code>self&#45;join</code>.

Вот пример запроса&#58;

```sql
SELECT e.name AS employee_name, m.name AS manager_name
FROM employees e
JOIN employees m ON e.manager_id = m.employee_id;
```

В этом запросе мы соединяем таблицу “<code>employees</code>” с самой собой, используя столбец “<code>manager_id</code>”, чтобы сопоставить каждого сотрудника с его руководителем. В результирующей таблице будут столбцы с именем сотрудника и именем его менеджера.

<code>Self&#45;join</code> также можно использовать для поиска связей между
данными в одной таблице. Например, если у вас есть таблица продуктов со
столбцами для ID продукта, названия и ID “родительского” продукта, соединение
внутри таблицы может быть использовано для поиска всех “дочерних” продуктов
данного “родительского” продукта.

:::note[Ссылки для изучения]

1. [Базовый синтаксис SQL](https://sql-academy.org/ru/guide/basic-syntax-sql-query)
   :::

---

## <strong>В чем разница между внутренним и внешним соединением?</strong> [#q-14bee738d69b8100aef6ed697a352c24]

Cоединения (joins, джоины) используются для комбинации данных из нескольких таблиц на основе общего столбца или их взаимоотношений. Два наиболее распространенных типа соединений – это внутреннее (<code>inner join</code>) и внешнее (<code>outer join</code>) соединения.

Внутреннее соединение возвращает только совпадающие строки из обеих таблиц на основе условия соединения. Например, если у нас есть две таблицы A и B, и мы выполняем внутреннее объединение с использованием общего столбца C, будут возвращены только те строки, в которых C совпадает в обеих таблицах.

Вот пример запроса для внутреннего соединения&#58;

```sql
SELECT A.column1, B.column2
FROM A
INNER JOIN B
ON A.C = B.C;
```

С другой стороны, внешнее соединение возвращает все строки из одной таблицы и совпадающие строки из другой таблицы. Если во второй таблице нет совпадающих строк, результат будет содержать NULL-значения для всех столбцов этой таблицы. Внешние соединения также делятся на левое внешнее (<code>left outer join</code>), правое внешнее (<code>right outer join</code>) и полное внешнее соединение (<code>full outer join</code>).

Вот пример запроса для левого внешнего соединения&#58;

```sql
SELECT A.column1, B.column2
FROM A
LEFT OUTER JOIN B
ON A.C = B.C;
```

Этот запрос вернет все строки из таблицы A и совпадающие строки из таблицы B на основе столбца C. Если в таблице B нет совпадающих строк, результат будет содержать NULL-значения для <code>column2</code>.

:::note[Ссылки для изучения]

1. [Базовый синтаксис SQL](https://sql-academy.org/ru/guide/basic-syntax-sql-query)
   :::

---

## <strong>В чем разница между коррелированным и некоррелированным подзапросом?</strong> [#q-14bee738d69b81c49e35f732f4facdce]

В SQL подзапрос – это запрос, который вложен в другой запрос, и он может быть как коррелированным, так и некоррелированным. Основное различие между ними заключается в том, как они ссылаются на внешний запрос.

Некоррелированный подзапрос может быть оценен независимо от внешнего запроса. Он не ссылается ни на один столбец внешнего запроса и может быть выполнен самостоятельно. Рассмотрим следующий пример, в котором используется некоррелированный подзапрос для получения данных о средней зарплате сотрудников (<code>AVG&#40;salary&#41;</code>)&#58;

```sql
SELECT first_name, last_name, salary
FROM employees
WHERE salary > (SELECT AVG(salary) FROM employees);
```

Подзапрос (<code>SELECT AVG&#40;salary&#41; FROM employees</code>) является некоррелированным подзапросом, поскольку может выполняться независимо от внешнего запроса. Он извлекает среднюю зарплату всех сотрудников, а результат используется в операторе <code>WHERE</code> внешнего запроса, чтобы отфильтровать сотрудников, чья зарплата больше средней.

С другой стороны, коррелированный подзапрос ссылается на один или несколько столбцов из внешнего запроса, используя значения из него. Рассмотрим пример, в котором используется коррелированный подзапрос для получения общего объема продаж для каждого сотрудника&#58;

```sql
SELECT first_name, last_name,
(SELECT SUM(amount) FROM sales WHERE sales.employee_id = employees.employee_id) AS total_sales
FROM employees;
```

Подзапрос (<code>SELECT SUM&#40;amount&#41; FROM sales WHERE sales&#46;employee_id &#61; employees&#46;employee_id</code>) является коррелированным, поскольку ссылается на столбец <code>employee_id</code> из внешнего запроса. Он оценивается для каждого сотрудника во внешнем запросе, и результат используется для расчета общего объема продаж для каждого сотрудника.

:::note[Ссылки для изучения]

1. [Базовый синтаксис SQL](https://sql-academy.org/ru/guide/basic-syntax-sql-query)
   :::

---

## <strong>Что такое обобщенное табличное выражение (</strong><code>CTE</code><strong>) и как оно используется?</strong> [#q-14bee738d69b8157ae3fd7cb86acd977]

CTE представляет именованный подзапрос, доступный в рамках одной SQL-команды. Он не обязательно хранится в памяти&#58; способ вычисления и материализации зависит от СУБД и плана.

<code>CTE</code> определяются с помощью ключевого слова <code>WITH</code>, за
которым следует имя <code>CTE</code> и подзапрос, определяющий его. Синтаксис
<code>CTE</code> выглядит следующим образом&#58;

```sql
WITH cte_name AS (
SELECT column1, column2, ...
FROM table_name
WHERE condition
)

SELECT *
FROM cte_name
```

На CTE можно ссылаться в основной команде, к которой относится WITH, и в допустимых последующих CTE этой же команды. В следующей отдельной SQL-команде он уже недоступен.

<code>CTE</code> также могут быть рекурсивными, что позволяет более эффективно
запрашивать иерархические данные. Рекурсивный <code>CTE</code> включает в себя
якорную часть и рекурсивную часть и может использоваться для перехода по
иерархии до тех пор, пока не будет выполнено определенное условие.

:::note[Ссылки для изучения]

1. [Базовый синтаксис SQL](https://sql-academy.org/ru/guide/basic-syntax-sql-query)
   :::

---

## <strong>Какие виды</strong> <code>JOINов</code> <strong>вы знаете?</strong> [#q-14bee738d69b814da537f1feee8d3d0d]

В SQL существует несколько типов <code>JOIN</code>&#58;

1&#46; <code>INNER JOIN</code>&#58; Возвращает строки, которые имеют соответствия в обеих таблицах.

2&#46; <code>LEFT JOIN</code> (или <code>LEFT OUTER JOIN</code>)&#58; Возвращает все строки из левой таблицы и соответствующие строки из правой таблицы. Если нет соответствия, то возвращается NULL для столбцов правой таблицы.

3&#46; <code>RIGHT JOIN</code> (или <code>RIGHT OUTER JOIN</code>)&#58; Возвращает все строки из правой таблицы и соответствующие строки из левой таблицы. Если нет соответствия, то возвращается NULL для столбцов левой таблицы.

4&#46; <code>FULL JOIN</code> (или <code>FULL OUTER JOIN</code>)&#58; Возвращает все строки из обеих таблиц. Если нет соответствия, то возвращается NULL для соответствующих столбцов.

5&#46; <code>CROSS JOIN</code>&#58; Возвращает декартово произведение двух таблиц, то есть все возможные комбинации строк из обеих таблиц.

:::note[Ссылки для изучения]

1. [Базовый синтаксис SQL](https://sql-academy.org/ru/guide/basic-syntax-sql-query)
   :::
