first commit
This commit is contained in:
758
labs/lab3/report.typ
Normal file
758
labs/lab3/report.typ
Normal file
@@ -0,0 +1,758 @@
|
||||
#show link: underline
|
||||
#set text(size: 1.3em)
|
||||
#set page(
|
||||
header: context {
|
||||
if counter(page).get().first() == 1 [
|
||||
#align(center)[
|
||||
Санкт-Петербургский национальный исследовательский университет информационных технологий, механики и оптики
|
||||
]
|
||||
]
|
||||
},
|
||||
footer: context {
|
||||
if counter(page).get().first() == 1 [
|
||||
#align(center)[Санкт-Петербург \ 2025]
|
||||
] else [
|
||||
#align(center)[#counter(page).display("1")]
|
||||
]
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
#show raw.where(block: false): box.with(
|
||||
fill: luma(240),
|
||||
inset: (x: 3pt, y: 0pt),
|
||||
outset: (y: 3pt),
|
||||
radius: 2pt,
|
||||
)
|
||||
|
||||
#show raw.where(block: true): block.with(
|
||||
fill: luma(240),
|
||||
inset: 10pt,
|
||||
radius: 4pt,
|
||||
)
|
||||
|
||||
// title
|
||||
|
||||
\
|
||||
\
|
||||
\
|
||||
#align(center)[Факультет инфокоммуникационных технологий]
|
||||
#align(center)[Направление подготовки 11.03.02]
|
||||
\
|
||||
\
|
||||
#align(center)[Практическая работа №3]
|
||||
//#align(center)[Установка и первоначальная настройка субд postgresql.]
|
||||
\
|
||||
\
|
||||
\
|
||||
\ //#align(center)[Вариант 19]
|
||||
\
|
||||
\
|
||||
\
|
||||
\
|
||||
\
|
||||
\
|
||||
\
|
||||
#align(right)[Выполнил:]
|
||||
#align(right)[Дощенников Никита Андреевич]
|
||||
#align(right)[Группа: К3221]
|
||||
#align(right)[Проверила:]
|
||||
#align(right)[Татьяна Евгеньевна Войтюк]
|
||||
|
||||
|
||||
#pagebreak()
|
||||
|
||||
=== Цель работы
|
||||
|
||||
Целью данной работы является изучение основных операций с базами данных на примере postgresql. В ходе работы мы учимся выполнять различные виды соединений таблиц, использовать агрегатные функции, группировать данные и получать сводную информацию о сотрудниках и отделах. Всё это позволяет лучше понять, как организуются данные в реальных информационных системах и как из них можно получать нужную информацию.
|
||||
|
||||
=== Задачи, решаемые при выполнении работы
|
||||
|
||||
В рамках работы необходимо выполнить несколько типов заданий. Сначала мы работаем с объединением таблиц, чтобы научиться получать информацию о сотрудниках, их отделах, руководителях и коллегах. Затем изучаем групповые функции, которые позволяют подсчитать количество сотрудников, средние и максимальные зарплаты, разницу окладов и другие показатели. Также нужно уметь фильтровать данные по различным условиям, сортировать результаты и использовать агрегирование, чтобы формировать отчёты по отделам и должностям.
|
||||
|
||||
=== Исходные данные
|
||||
|
||||
Для выполнения работы использовалась база данных, содержащая таблицы с информацией о сотрудниках, отделах, местоположениях, странах и регионах. Таблицы включают такие поля, как имя, фамилия, идентификатор сотрудника, должность, зарплата, бонус, дата найма, идентификатор отдела и руководителя. Эти данные позволяют выполнять все необходимые запросы: соединять таблицы, группировать и фильтровать информацию, а также анализировать структуру и показатели работы сотрудников и отделов.
|
||||
|
||||
=== Выполнение работы
|
||||
// формирование запроса, краткое описание используемых конструкций/функций при необходимости. Предоставляется возможность дополнить отчет скриншотами результатов.
|
||||
|
||||
==== Задание 1. Использование объединения таблиц
|
||||
|
||||
===== 1.1
|
||||
|
||||
*Напишите запрос для вывода фамилии, имени, названия отдела для всех работников, в фамилии которых есть буква «u» (в строчном регистре). Укажите, какой тип соединения таблиц используется в данном запросе, и задокументируйте результат его выполнения.*
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
e."LAST_NAME",
|
||||
e."FIRST_NAME",
|
||||
d."DEPARTMENT_NAME"
|
||||
FROM "EmployeesDepartments"."EMPLOYEES" e
|
||||
JOIN "EmployeesDepartments"."DEPARTMENTS" d
|
||||
ON e."DEPARTMENT_ID" = d."DEPARTMENT_ID"
|
||||
WHERE e."LAST_NAME" LIKE '%u%';
|
||||
```
|
||||
|
||||
- Соединяем таблицы `EMPLOYEES` и `DEPARTMENTS` по `DEPARTMENT_ID` с помощью `INNER JOIN`.
|
||||
- Выбираем фамилию, имя и название отдела.
|
||||
- Фильтруем только тех сотрудников, у которых фамилия содержит букву «u».
|
||||
|
||||
#align(center)[
|
||||
#figure(
|
||||
image("assets/1.png"),
|
||||
supplement: [Рис.],
|
||||
caption: [Результат выполнения запроса задания 1.1]
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
===== 1.2
|
||||
|
||||
*Напишите запрос для вывода имени, фамилии, названия должности и названия отдела для всех работников. Отсортируйте результат по идентификатору работника. Укажите, какой тип соединения таблиц используется в данном запросе, и задокументируйте результат его выполнения.*
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
e."FIRST_NAME",
|
||||
e."LAST_NAME",
|
||||
e."JOB_ID",
|
||||
d."DEPARTMENT_NAME"
|
||||
FROM "EmployeesDepartments"."EMPLOYEES" e
|
||||
JOIN "EmployeesDepartments"."DEPARTMENTS" d
|
||||
ON e."DEPARTMENT_ID" = d."DEPARTMENT_ID"
|
||||
ORDER BY e."EMPLOYEE_ID";
|
||||
```
|
||||
|
||||
- Соединяем `EMPLOYEES` и `DEPARTMENTS` по `DEPARTMENT_ID` через `INNER JOIN`.
|
||||
- Выбираем имя, фамилию, должность и отдел сотрудника.
|
||||
- Сортируем по `EMPLOYEE_ID` для просмотра всех сотрудников по порядку.
|
||||
|
||||
#align(center)[
|
||||
#figure(
|
||||
image("assets/2.png"),
|
||||
supplement: [Рис.],
|
||||
caption: [Результат выполнения запроса задания 1.2]
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
===== 1.3
|
||||
|
||||
*Напишите запрос для вывода названия отдела, фамилии и имени сотрудника для всех сотрудников, у которых есть бонус, работающих в 80-ом и 85-ом отделах. Полученный результат отсортируйте по номеру отдела, размеру бонуса по убыванию, а затем фамилии. Укажите, какой тип соединения таблиц используется в данном запросе, и задокументируйте результат его выполнения.*
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
d."DEPARTMENT_NAME",
|
||||
e."LAST_NAME",
|
||||
e."FIRST_NAME",
|
||||
e."COMMISSION_PCT" AS "Bonus"
|
||||
FROM "EmployeesDepartments"."EMPLOYEES" e
|
||||
JOIN "EmployeesDepartments"."DEPARTMENTS" d
|
||||
ON e."DEPARTMENT_ID" = d."DEPARTMENT_ID"
|
||||
WHERE e."COMMISSION_PCT" IS NOT NULL
|
||||
AND e."DEPARTMENT_ID" IN (80, 85)
|
||||
ORDER BY e."DEPARTMENT_ID", e."COMMISSION_PCT" DESC, e."LAST_NAME";
|
||||
```
|
||||
|
||||
- Выбираем сотрудников из отделов 80 и 85 с ненулевым бонусом.
|
||||
- Соединяем таблицы сотрудников и отделов через `INNER JOIN`.
|
||||
- Сортируем по номер отдела, бонус по убыванию, фамилия.
|
||||
- В результате видны только сотрудники с бонусом и существующим отделом.
|
||||
|
||||
#align(center)[
|
||||
#figure(
|
||||
image("assets/3.png"),
|
||||
supplement: [Рис.],
|
||||
caption: [Результат выполнения запроса задания 1.3]
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
===== 1.4
|
||||
|
||||
*Напишите запрос для вывода фамилии, имени, названия страны и региона для всех работников, работающих в Северной Америке. Отсортируйте результат по названию страны и фамилии сотрудника. Укажите, какой тип соединения таблиц используется в данном запросе, и задокументируйте результат его выполнения.*
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
e."LAST_NAME",
|
||||
e."FIRST_NAME",
|
||||
c."COUNTRY_NAME",
|
||||
r."REGION_NAME"
|
||||
FROM "EmployeesDepartments"."EMPLOYEES" e
|
||||
JOIN "EmployeesDepartments"."DEPARTMENTS" d
|
||||
ON e."DEPARTMENT_ID" = d."DEPARTMENT_ID"
|
||||
JOIN "EmployeesDepartments"."LOCATIONS" l
|
||||
ON d."LOCATION_ID" = l."LOCATION_ID"
|
||||
JOIN "Countries"."COUNTRIES" c
|
||||
ON l."COUNTRY_ID" = c."COUNTRY_ID"
|
||||
JOIN "Countries"."REGIONS" r
|
||||
ON c."REGION_ID" = r."REGION_ID"
|
||||
WHERE r."REGION_NAME" = 'Americas'
|
||||
ORDER BY c."COUNTRY_NAME", e."LAST_NAME";
|
||||
```
|
||||
|
||||
- Соединяем сотрудников, отделы, локации, страны, регионы
|
||||
- Используем `INNER JOIN`
|
||||
- Фильтруем регион `Americas`
|
||||
- Сортируем по стране и фамилии сотрудника
|
||||
|
||||
#align(center)[
|
||||
#figure(
|
||||
image("assets/4.png"),
|
||||
supplement: [Рис.],
|
||||
caption: [Результат выполнения запроса задания 1.4]
|
||||
)
|
||||
]
|
||||
|
||||
===== 1.5
|
||||
|
||||
*Напишите запрос для вывода фамилии и идентификатора работника, а также фамилии и идентификатора его начальника. Назовите столбцы результата «Подчиненный», «Идентификатор работника», «Руководитель», «Идентификатор руководителя». Отсортируйте результат по идентификатору руководителя по возрастанию и по идентификатору работника по убыванию. Укажите, какой тип соединения таблиц используется в данном запросе, и задокументируйте результат его выполнения.*
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
e."LAST_NAME" AS "Подчиненный",
|
||||
e."EMPLOYEE_ID" AS "Идентификатор работника",
|
||||
m."LAST_NAME" AS "Руководитель",
|
||||
m."EMPLOYEE_ID" AS "Идентификатор руководителя"
|
||||
FROM "EmployeesDepartments"."EMPLOYEES" e
|
||||
LEFT JOIN "EmployeesDepartments"."EMPLOYEES" m
|
||||
ON e."MANAGER_ID" = m."EMPLOYEE_ID"
|
||||
ORDER BY m."EMPLOYEE_ID" ASC, e."EMPLOYEE_ID" DESC;
|
||||
```
|
||||
|
||||
- Используется `LEFT JOIN`, чтобы включить всех сотрудников, даже если у них нет начальника.
|
||||
- Сортировка сначала по ID менеджера, потом по ID сотрудника.
|
||||
|
||||
#align(center)[
|
||||
#figure(
|
||||
image("assets/5.png"),
|
||||
supplement: [Рис.],
|
||||
caption: [Результат выполнения запроса задания 1.5]
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
===== 1.6
|
||||
|
||||
*Измените запрос из пункта 1.5. таким образом, чтобы получить фамилии всех работников в столбце «Подчиненный», включая Кинга, который не имеет руководителя. Отсортируйте результат по идентификатору подчиненного, укажите, какой тип соединения таблиц используется в данном запросе, и задокументируйте результат его выполнения.*
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
e."LAST_NAME" AS "Подчиненный",
|
||||
e."EMPLOYEE_ID" AS "Идентификатор подчиненного",
|
||||
m."LAST_NAME" AS "Руководитель",
|
||||
m."EMPLOYEE_ID" AS "Идентификатор руководителя"
|
||||
FROM "EmployeesDepartments"."EMPLOYEES" e
|
||||
LEFT JOIN "EmployeesDepartments"."EMPLOYEES" m
|
||||
ON e."MANAGER_ID" = m."EMPLOYEE_ID"
|
||||
ORDER BY e."EMPLOYEE_ID";
|
||||
```
|
||||
|
||||
- Используем `LEFT JOIN` таблицы `EMPLOYEES`, чтобы получить и менеджеров, и всех подчинённых, включая тех, у кого нет руководителя.
|
||||
- Сортировка выполняется по ID подчинённого для удобного просмотра.
|
||||
|
||||
#align(center)[
|
||||
#figure(
|
||||
image("assets/6.png"),
|
||||
supplement: [Рис.],
|
||||
caption: [Результат выполнения запроса задания 1.6]
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
===== 1.7
|
||||
|
||||
*Напишите запрос для вывода названия отдела, фамилии сотрудника и фамилий всех его коллег для сотрудников Fay, Hartstein и Davies. Назовите столбцы результата «Отдел», «Работник», «Коллеги». Отсортируйте результат по отделу и фамилии сотрудника. Укажите, какой тип соединения таблиц используется в данном запросе, и задокументируйте результат его выполнения.*
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
d."DEPARTMENT_NAME" AS "Отдел",
|
||||
e1."LAST_NAME" AS "Работник",
|
||||
STRING_AGG(e2."LAST_NAME", ', ') AS "Коллеги"
|
||||
FROM "EmployeesDepartments"."EMPLOYEES" e1
|
||||
JOIN "EmployeesDepartments"."DEPARTMENTS" d
|
||||
ON e1."DEPARTMENT_ID" = d."DEPARTMENT_ID"
|
||||
JOIN "EmployeesDepartments"."EMPLOYEES" e2
|
||||
ON e1."DEPARTMENT_ID" = e2."DEPARTMENT_ID"
|
||||
AND e1."EMPLOYEE_ID" <> e2."EMPLOYEE_ID"
|
||||
WHERE e1."LAST_NAME" IN ('Fay', 'Hartstein', 'Davies')
|
||||
GROUP BY d."DEPARTMENT_NAME", e1."LAST_NAME"
|
||||
ORDER BY d."DEPARTMENT_NAME", e1."LAST_NAME";
|
||||
```
|
||||
|
||||
- Используем `JOIN`, чтобы найти коллег по одному отделу, исключая самого сотрудника.
|
||||
- Применяем `STRING_AGG` для объединения всех фамилий коллег в одну строку.
|
||||
- Фильтруем только выбранных сотрудников и сортируем результат по отделу и фамилии.
|
||||
|
||||
#align(center)[
|
||||
#figure(
|
||||
image("assets/7.png"),
|
||||
supplement: [Рис.],
|
||||
caption: [Результат выполнения запроса задания 1.7]
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
===== 1.8
|
||||
|
||||
*Напишите запрос для вывода всех категорий работников (GRADE_LEVEL), их фамилий, размеров оклада, названий должностей и названий отделов. Если в некоторой категории нет работников, то эта категория всё равно должна присутствовать в результате. Отсортируйте результат по категории работника, отделу и фамилии. Укажите, какой тип соединения таблиц используется в данном запросе, и задокументируйте результат его выполнения.*
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
jg."GRADE_LEVEL" AS "Категория",
|
||||
e."LAST_NAME" AS "Фамилия",
|
||||
e."SALARY" AS "Оклад",
|
||||
e."JOB_ID" AS "Должность",
|
||||
d."DEPARTMENT_NAME" AS "Отдел"
|
||||
FROM "EmployeesDepartments"."JOB_GRADES" jg
|
||||
LEFT JOIN "EmployeesDepartments"."EMPLOYEES" e
|
||||
ON e."SALARY" BETWEEN jg."LOWEST_SAL" AND jg."HIGHEST_SAL"
|
||||
LEFT JOIN "EmployeesDepartments"."DEPARTMENTS" d
|
||||
ON e."DEPARTMENT_ID" = d."DEPARTMENT_ID"
|
||||
ORDER BY jg."GRADE_LEVEL", d."DEPARTMENT_NAME", e."LAST_NAME";
|
||||
```
|
||||
|
||||
- Основная таблица — `JOB_GRADES`.
|
||||
- Сотрудники и отделы присоединяются через `LEFT JOIN`.
|
||||
- Таким образом, категории без работников всё равно будут отображаться.
|
||||
- Результат отсортирован по категории, отдел, фамилия.
|
||||
|
||||
#align(center)[
|
||||
#figure(
|
||||
image("assets/8.png"),
|
||||
supplement: [Рис.],
|
||||
caption: [Результат выполнения запроса задания 1.8]
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
===== 1.9
|
||||
|
||||
*Напишите запрос для вывода фамилий и дат найма всех сотрудников, а также фамилий и дат найма их руководителей, для всех сотрудников, руководители которых устроились на работу в 2008ом году, но при это сами подчиненные устроились на работу до 2008 года. Укажите, какой тип соединения таблиц используется в данном запросе, и задокументируйте результат его выполнения.*
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
e."LAST_NAME" AS "Сотрудник",
|
||||
e."HIRE_DATE" AS "Дата найма сотрудника",
|
||||
m."LAST_NAME" AS "Руководитель",
|
||||
m."HIRE_DATE" AS "Дата найма руководителя"
|
||||
FROM "EmployeesDepartments"."EMPLOYEES" e
|
||||
JOIN "EmployeesDepartments"."EMPLOYEES" m
|
||||
ON e."MANAGER_ID" = m."EMPLOYEE_ID"
|
||||
WHERE EXTRACT(YEAR FROM m."HIRE_DATE") = 2008
|
||||
AND EXTRACT(YEAR FROM e."HIRE_DATE") < 2008
|
||||
ORDER BY m."LAST_NAME", e."LAST_NAME";
|
||||
```
|
||||
|
||||
- Соединяем сотрудников с их руководителями `JOIN`.
|
||||
- Фильтруем по дате найма: подчинённый до 2008, руководитель — 2008.
|
||||
|
||||
#align(center)[
|
||||
#figure(
|
||||
image("assets/9.png"),
|
||||
supplement: [Рис.],
|
||||
caption: [Результат выполнения запроса задания 1.9]
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
===== 1.10
|
||||
|
||||
*Для всех работников, менеджеры которых устроились на работу в январе, и длина названий должностей этих работников(подчиненных) более 15ти символов, сформируйте запрос для вывода названия должности, фамилии работника, даты найма, фамилии руководителя и его даты найма. Результат отсортировать по названию должности, фамилии руководителя, идентификатору работника. Укажите, какой тип соединения таблиц используется в данном запросе, и задокументируйте результат его выполнения.*
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
e."JOB_ID" AS "Должность",
|
||||
e."LAST_NAME" AS "Сотрудник",
|
||||
e."HIRE_DATE" AS "Дата найма сотрудника",
|
||||
m."LAST_NAME" AS "Руководитель",
|
||||
m."HIRE_DATE" AS "Дата найма руководителя"
|
||||
FROM "EmployeesDepartments"."EMPLOYEES" e
|
||||
JOIN "EmployeesDepartments"."EMPLOYEES" m
|
||||
ON e."MANAGER_ID" = m."EMPLOYEE_ID"
|
||||
WHERE EXTRACT(MONTH FROM m."HIRE_DATE") = 1
|
||||
AND LENGTH(e."JOB_ID") > 15
|
||||
ORDER BY e."JOB_ID", m."LAST_NAME", e."EMPLOYEE_ID";
|
||||
```
|
||||
|
||||
- Соединяем сотрудников с их менеджерами `JOIN`.
|
||||
- Фильтруем менеджеров, нанятых в январе, и подчинённых с длинной должностью > 15 символов.
|
||||
- Сортировка по должности, фамилия руководителя, ID сотрудника.
|
||||
|
||||
#align(center)[
|
||||
#figure(
|
||||
image("assets/10.png"),
|
||||
supplement: [Рис.],
|
||||
caption: [Результат выполнения запроса задания 1.10]
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
===== 1.11
|
||||
|
||||
*Напишите запрос для вывода идентификатора отдела и его названия для всех отделов, в которых нет работников. Укажите, какой тип соединения таблиц используется в данном запросе, и задокументируйте результат его выполнения.*
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
d."DEPARTMENT_ID",
|
||||
d."DEPARTMENT_NAME"
|
||||
FROM "EmployeesDepartments"."DEPARTMENTS" d
|
||||
LEFT JOIN "EmployeesDepartments"."EMPLOYEES" e
|
||||
ON d."DEPARTMENT_ID" = e."DEPARTMENT_ID"
|
||||
WHERE e."EMPLOYEE_ID" IS NULL
|
||||
ORDER BY d."DEPARTMENT_ID";
|
||||
```
|
||||
|
||||
- Используется `LEFT JOIN` для включения всех отделов.
|
||||
- Отбираем только те отделы, где нет сотрудников.
|
||||
- Сортируем результат по ID отдела.
|
||||
|
||||
#align(center)[
|
||||
#figure(
|
||||
image("assets/11.png"),
|
||||
supplement: [Рис.],
|
||||
caption: [Результат выполнения запроса задания 1.11]
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
==== Задание 2. Использование групповых функций
|
||||
|
||||
===== 2.1
|
||||
|
||||
*Напишите запрос для вывода идентификатора отдела, количества работников в нём, минимальной, максимальной и средней заработной платы по отделу, а также дат первого и последнего приёма в отдел. Для всех столбцов результата задайте понятные наименования и отсортируйте результат по количеству сотрудников (по убыванию). Задокументируйте результат выполнения запроса.*
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
d."DEPARTMENT_ID" AS "ID отдела",
|
||||
COUNT(e."EMPLOYEE_ID") AS "Количество сотрудников",
|
||||
MIN(e."SALARY") AS "Минимальная зарплата",
|
||||
MAX(e."SALARY") AS "Максимальная зарплата",
|
||||
ROUND(AVG(e."SALARY"), 2) AS "Средняя зарплата",
|
||||
MIN(e."HIRE_DATE") AS "Дата первого приема",
|
||||
MAX(e."HIRE_DATE") AS "Дата последнего приема"
|
||||
FROM "EmployeesDepartments"."DEPARTMENTS" d
|
||||
LEFT JOIN "EmployeesDepartments"."EMPLOYEES" e
|
||||
ON d."DEPARTMENT_ID" = e."DEPARTMENT_ID"
|
||||
GROUP BY d."DEPARTMENT_ID"
|
||||
ORDER BY "Количество сотрудников" DESC;
|
||||
```
|
||||
|
||||
- Используем `LEFT JOIN` для включения всех отделов.
|
||||
- Считаем количество сотрудников, минимальные/максимальные/средние зарплаты и даты первого/последнего приема.
|
||||
- Сортируем результат по количеству сотрудников в отделе по убыванию.
|
||||
|
||||
#align(center)[
|
||||
#figure(
|
||||
image("assets/12.png"),
|
||||
supplement: [Рис.],
|
||||
caption: [Результат выполнения запроса задания 2.1]
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
===== 2.2
|
||||
|
||||
*Напишите запрос для вывода названия должности, самого низкого, самого высокого и среднего оклада по ней, а также суммы окладов по каждой должности. Отсортируйте результат по названию должности и задокументируйте результат выполнения запроса.*
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
e."JOB_ID" AS "Должность",
|
||||
MIN(e."SALARY") AS "Минимальный оклад",
|
||||
MAX(e."SALARY") AS "Максимальный оклад",
|
||||
ROUND(AVG(e."SALARY"), 2) AS "Средний оклад",
|
||||
SUM(e."SALARY") AS "Сумма окладов"
|
||||
FROM "EmployeesDepartments"."EMPLOYEES" e
|
||||
GROUP BY e."JOB_ID"
|
||||
ORDER BY e."JOB_ID";
|
||||
```
|
||||
|
||||
- Используем агрегатные функции для вычисления минимального, максимального, среднего и суммарного оклада по каждой должности.
|
||||
- Группируем сотрудников по `JOB_ID`.
|
||||
- Сортировка выполняется по названию должности.
|
||||
|
||||
#align(center)[
|
||||
#figure(
|
||||
image("assets/13.png"),
|
||||
supplement: [Рис.],
|
||||
caption: [Результат выполнения запроса задания 2.2]
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
===== 2.3
|
||||
|
||||
*Напишите запрос, который позволяет получить список отделов (идентификаторов отделов), их наименований и округленную среднюю заработную плату работников в каждом из них. Для всех столбцов результата задайте понятные наименования, отсортируйте по округленной средней заработной плате и задокументируйте результат выполнения запроса.*
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
d."DEPARTMENT_ID" AS "ID отдела",
|
||||
d."DEPARTMENT_NAME" AS "Название отдела",
|
||||
ROUND(AVG(e."SALARY"), 2) AS "Средняя зарплата"
|
||||
FROM "EmployeesDepartments"."DEPARTMENTS" d
|
||||
LEFT JOIN "EmployeesDepartments"."EMPLOYEES" e
|
||||
ON d."DEPARTMENT_ID" = e."DEPARTMENT_ID"
|
||||
GROUP BY d."DEPARTMENT_ID", d."DEPARTMENT_NAME"
|
||||
ORDER BY "Средняя зарплата";
|
||||
```
|
||||
|
||||
- Используем `LEFT JOIN` для включения всех отделов.
|
||||
- Средняя зарплата вычисляется функцией `AVG` и округляется через `ROUND`.
|
||||
- Сортируем результат по средней зарплате.
|
||||
|
||||
#align(center)[
|
||||
#figure(
|
||||
image("assets/14.png"),
|
||||
supplement: [Рис.],
|
||||
caption: [Результат выполнения запроса задания 2.3]
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
===== 2.4
|
||||
|
||||
*Напишите запрос, который позволяет получить список руководителей (их имя, фамилию, должность), у которых количество подчиненных больше 5 и сумма всех зарплат его подчиненных больше 50000. Задокументируйте результат выполнения запроса.*
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
m."FIRST_NAME" AS "Имя",
|
||||
m."LAST_NAME" AS "Фамилия",
|
||||
m."JOB_ID" AS "Должность",
|
||||
COUNT(e."EMPLOYEE_ID") AS "Количество подчинённых",
|
||||
SUM(e."SALARY") AS "Сумма зарплат подчинённых"
|
||||
FROM "EmployeesDepartments"."EMPLOYEES" m
|
||||
JOIN "EmployeesDepartments"."EMPLOYEES" e
|
||||
ON e."MANAGER_ID" = m."EMPLOYEE_ID"
|
||||
GROUP BY m."EMPLOYEE_ID", m."FIRST_NAME", m."LAST_NAME", m."JOB_ID"
|
||||
HAVING COUNT(e."EMPLOYEE_ID") > 5
|
||||
AND SUM(e."SALARY") > 50000
|
||||
ORDER BY "Количество подчинённых" DESC;
|
||||
```
|
||||
|
||||
- `JOIN` позволяет сопоставить руководителя с его подчинёнными.
|
||||
- Используем `COUNT` и `SUM` для подсчёта и суммы зарплат.
|
||||
- `HAVING` фильтрует руководителей по заданным критериям.
|
||||
|
||||
#align(center)[
|
||||
#figure(
|
||||
image("assets/15.png"),
|
||||
supplement: [Рис.],
|
||||
caption: [Результат выполнения запроса задания 2.4]
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
===== 2.5
|
||||
|
||||
*Напишите запрос для вывода идентификатора отдела и разности между самым высоким и самым низким окладами по каждому отделу. Результат отсортируйте по убыванию разности окладов.*
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
e."DEPARTMENT_ID" AS "ID отдела",
|
||||
(MAX(e."SALARY") - MIN(e."SALARY")) AS "Разница окладов"
|
||||
FROM "EmployeesDepartments"."EMPLOYEES" e
|
||||
GROUP BY e."DEPARTMENT_ID"
|
||||
ORDER BY "Разница окладов" DESC;
|
||||
```
|
||||
|
||||
- Используем `MAX` и `MIN` для вычисления диапазона зарплат в каждом отделе.
|
||||
- Группировка по отделу позволяет рассчитать разницу окладов на уровне каждого отдела.
|
||||
- Сортируем результат по убыванию разницы.
|
||||
|
||||
#align(center)[
|
||||
#figure(
|
||||
image("assets/16.png"),
|
||||
supplement: [Рис.],
|
||||
caption: [Результат выполнения запроса задания 2.5]
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
===== 2.6
|
||||
|
||||
*Напишите запрос для вывода идентификатора каждого руководителя, имеющего подчинённых, и средней заработной платы этих подчинённых, но только для тех руководителей, которые не получают бонусов, и у которых средняя заработная плата подчинённых находится в диапазоне от 6000 до 9000. Отсортируйте результат по идентификатору руководителя и задокументируйте результат выполнения запроса.*
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
m."EMPLOYEE_ID" AS "ID руководителя",
|
||||
ROUND(AVG(e."SALARY"), 2) AS "Средняя зарплата подчинённых"
|
||||
FROM "EmployeesDepartments"."EMPLOYEES" m
|
||||
JOIN "EmployeesDepartments"."EMPLOYEES" e
|
||||
ON e."MANAGER_ID" = m."EMPLOYEE_ID"
|
||||
WHERE m."COMMISSION_PCT" IS NULL
|
||||
GROUP BY m."EMPLOYEE_ID"
|
||||
HAVING AVG(e."SALARY") BETWEEN 6000 AND 9000
|
||||
ORDER BY m."EMPLOYEE_ID";
|
||||
```
|
||||
|
||||
- `Self JOIN` позволяет сопоставить руководителя с его подчинёнными.
|
||||
- Фильтруем руководителей без бонуса и подбираем только тех, у кого средняя зарплата подчинённых в заданном диапазоне.
|
||||
|
||||
#align(center)[
|
||||
#figure(
|
||||
image("assets/17.png"),
|
||||
supplement: [Рис.],
|
||||
caption: [Результат выполнения запроса задания 2.6]
|
||||
)
|
||||
]
|
||||
|
||||
===== 2.7
|
||||
|
||||
*Напишите запрос для вывода названия отдела, местоположения отдела (город, адрес) и количества служащих в нём, но только для тех отделов, в которых работники занимают различные должности. Для всех столбцов результата задайте понятные наименования и отсортируйте результат по количеству служащих (по убыванию). Результат выполнения запроса задокументируйте.*
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
d."DEPARTMENT_NAME" AS "Отдел",
|
||||
l."CITY" || ', ' || l."STREET_ADDRESS" AS "Местоположение",
|
||||
COUNT(e."EMPLOYEE_ID") AS "Количество сотрудников"
|
||||
FROM "EmployeesDepartments"."DEPARTMENTS" d
|
||||
JOIN "EmployeesDepartments"."EMPLOYEES" e
|
||||
ON d."DEPARTMENT_ID" = e."DEPARTMENT_ID"
|
||||
JOIN "EmployeesDepartments"."LOCATIONS" l
|
||||
ON d."LOCATION_ID" = l."LOCATION_ID"
|
||||
GROUP BY d."DEPARTMENT_NAME", l."CITY", l."STREET_ADDRESS", d."DEPARTMENT_ID"
|
||||
HAVING COUNT(DISTINCT e."JOB_ID") > 1
|
||||
ORDER BY "Количество сотрудников" DESC;
|
||||
```
|
||||
|
||||
- Соединяем отделы с сотрудниками и местоположениями `INNER JOIN`.
|
||||
- Считаем количество сотрудников и проверяем, что в отделе есть различные должности.
|
||||
|
||||
#align(center)[
|
||||
#figure(
|
||||
image("assets/18.png"),
|
||||
supplement: [Рис.],
|
||||
caption: [Результат выполнения запроса задания 2.7]
|
||||
)
|
||||
]
|
||||
|
||||
===== 2.8
|
||||
|
||||
*Напишите запрос для вывода года и количества принятых на работу сотрудников в указанном году по всем годам. Результат отсортировать по количеству принятых на работу сотрудников в год и задокументировать.*
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
EXTRACT(YEAR FROM e."HIRE_DATE") AS "Год",
|
||||
COUNT(e."EMPLOYEE_ID") AS "Количество принятых"
|
||||
FROM "EmployeesDepartments"."EMPLOYEES" e
|
||||
GROUP BY EXTRACT(YEAR FROM e."HIRE_DATE")
|
||||
ORDER BY "Количество принятых" DESC;
|
||||
```
|
||||
|
||||
- Извлекаем год найма с помощью `EXTRACT(YEAR ...)`.
|
||||
- Считаем количество сотрудников, принятых в каждый год `COUNT`.
|
||||
- Сортируем по количеству принятых сотрудников по убыванию.
|
||||
|
||||
#align(center)[
|
||||
#figure(
|
||||
image("assets/19.png"),
|
||||
supplement: [Рис.],
|
||||
caption: [Результат выполнения запроса задания 2.8]
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
===== 2.9
|
||||
|
||||
*Напишите запрос, который выводит длину имени и количество сотрудников с соответствующей длиной имени. В результат включите только тех сотрудников, у которых длина имени больше 5, а количество сотрудников с такой длиной — больше 3. Результат отсортируйте по длине имени и задокументируйте.*
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
LENGTH(e."FIRST_NAME") AS "Длина имени",
|
||||
COUNT(e."EMPLOYEE_ID") AS "Количество сотрудников"
|
||||
FROM "EmployeesDepartments"."EMPLOYEES" e
|
||||
WHERE LENGTH(e."FIRST_NAME") > 5
|
||||
GROUP BY LENGTH(e."FIRST_NAME")
|
||||
HAVING COUNT(e."EMPLOYEE_ID") > 3
|
||||
ORDER BY "Длина имени";
|
||||
```
|
||||
|
||||
- Считаем количество сотрудников по длине имени `LENGTH + COUNT`.
|
||||
- Отбираем только имена длиннее 5 символов и длины, встречающиеся у более чем 3 сотрудников.
|
||||
- Сортируем результат по длине имени.
|
||||
|
||||
#align(center)[
|
||||
#figure(
|
||||
image("assets/20.png"),
|
||||
supplement: [Рис.],
|
||||
caption: [Результат выполнения запроса задания 2.9]
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
===== 2.10
|
||||
|
||||
*Напишите запрос, который выводит названия отделов, их идентификационный номер, адрес и город, а также количество работников в каждом отделе, включая те, где пока нет ни одного работника. Укажите, какой тип соединения таблиц используется в данном запросе. Для всех столбцов результата задайте понятные наименования, отсортируйте по номеру отдела и задокументируйте.*
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
d."DEPARTMENT_NAME" AS "Название отдела",
|
||||
d."DEPARTMENT_ID" AS "ID отдела",
|
||||
l."STREET_ADDRESS" AS "Адрес",
|
||||
l."CITY" AS "Город",
|
||||
COUNT(e."EMPLOYEE_ID") AS "Количество сотрудников"
|
||||
FROM "EmployeesDepartments"."DEPARTMENTS" d
|
||||
LEFT JOIN "EmployeesDepartments"."EMPLOYEES" e
|
||||
ON d."DEPARTMENT_ID" = e."DEPARTMENT_ID"
|
||||
JOIN "EmployeesDepartments"."LOCATIONS" l
|
||||
ON d."LOCATION_ID" = l."LOCATION_ID"
|
||||
GROUP BY d."DEPARTMENT_ID", d."DEPARTMENT_NAME", l."STREET_ADDRESS", l."CITY"
|
||||
ORDER BY d."DEPARTMENT_ID";
|
||||
```
|
||||
|
||||
- Считаем количество сотрудников в каждом отделе, включая отделы без сотрудников `LEFT JOIN`.
|
||||
- Получаем адрес и город через соединение с `LOCATIONS`.
|
||||
- Результат отсортирован по номеру отдела.
|
||||
|
||||
#align(center)[
|
||||
#figure(
|
||||
image("assets/21.png"),
|
||||
supplement: [Рис.],
|
||||
caption: [Результат выполнения запроса задания 2.10]
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
===== 2.11
|
||||
|
||||
*Напишите запрос, который выводит название должности, количество работников, занимающих эту должность, а также среднюю заработную плату по каждой должности в отделах Administration и IT. В результат включите только те должности, где средняя зарплата превышает 4000, и на которых работает более двух сотрудников. Для всех столбцов результата задайте понятные наименования, отсортируйте данные по убыванию количества сотрудников и задокументируйте.*
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
e."JOB_ID" AS "Должность",
|
||||
COUNT(e."EMPLOYEE_ID") AS "Количество сотрудников",
|
||||
ROUND(AVG(e."SALARY"), 2) AS "Средняя зарплата"
|
||||
FROM "EmployeesDepartments"."EMPLOYEES" e
|
||||
JOIN "EmployeesDepartments"."DEPARTMENTS" d
|
||||
ON e."DEPARTMENT_ID" = d."DEPARTMENT_ID"
|
||||
WHERE d."DEPARTMENT_NAME" IN ('Administration', 'IT')
|
||||
GROUP BY e."JOB_ID"
|
||||
HAVING COUNT(e."EMPLOYEE_ID") > 2
|
||||
AND AVG(e."SALARY") > 4000
|
||||
ORDER BY "Количество сотрудников" DESC;
|
||||
```
|
||||
|
||||
- Соединяем таблицы сотрудников и отделов.
|
||||
- Фильтруем только нужные отделы.
|
||||
- Группируем по должности и считаем количество сотрудников и среднюю зарплату.
|
||||
- Фильтруем по условиям `HAVING` и сортируем результат по количеству сотрудников.
|
||||
|
||||
#align(center)[
|
||||
#figure(
|
||||
image("assets/22.png"),
|
||||
supplement: [Рис.],
|
||||
caption: [Результат выполнения запроса задания 2.11]
|
||||
)
|
||||
]
|
||||
|
||||
=== Выводы и анализ результатов работы
|
||||
// Обобщение результатов выполнения всех задач работы: что должны были достичь, что фактически достигли и каким образом, с какими трудностями столкнулись, какие проблемы на каких этапах выполнения возникли и как именно были решены.
|
||||
|
||||
В ходе выполнения работы удалось последовательно отработать ключевые навыки работы с реляционными базами данных. Основной целью было научиться применять различные виды соединений таблиц, фильтрацию, группировку, агрегирование и оформление результатов. Все эти задачи были выполнены: мы строили запросы с `INNER JOIN`, исследовали структуру связанных таблиц, получали данные о сотрудниках и отделах, вычисляли агрегаты и формировали отчёты, соответствующие условиям заданий.
|
||||
|
||||
Удалось добиться полного понимания, как извлекать данные из нескольких таблиц и объединять их в единую осмысленную выборку. Отдельные задания требовали работы с условиями, правильного выбора типа соединения и обращения к именованным полям.
|
||||
|
||||
В итоге была закреплена практика использования агрегатных функций, фильтрации по шаблону, сортировки результатов. Работа показала, как шаг за шагом строится аналитика поверх обычных данных, и позволила сформировать цельное понимание того, как sql-запросы применяются для анализа и обработки информации в реальных базах данных.
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user