Добавил:
ИВТ (советую зайти в "Несортированное") Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
33
Добавлен:
21.09.2024
Размер:
1.16 Mб
Скачать
  1. Практическая часть

    1. Задание 1.

with count_degree AS (

SELECT DISTINCT degree from professors

) SELECT count(degree) FROM count_degree

Рассмотрите следующий запрос. Какой результат был получен после его выполнения. Измените запрос, поставив вместе значения degree в агрегатную функцию символ «*». Сравните результаты выполнения запросов и объясните его.

В первом примере он вывел только небольшое кол-во уникальных значений, которые подходят, а во втором все * - все уникальные значения типо которые отличаются

Основной запрос подсчитывает количество строк в этой временной таблице, то есть фактически считает количество уникальных значений в столбце degree.

Результат: Вернется количество уникальных степеней, присутствующих в таблице professors

    1. Задание 2.

Напишите SQL запросы к учебной базе данных в соответствии с вариантом. Вариант к практической части выбирается по формуле: V = (N % 10) +1, где N – номер в списке группы, % - остаток от деления. Обратите внимание, что группировка заданий по разделам означает не столько подсказку, сколько обязательное использование данных параметров. Некоторые запросы возможно решить без использования указанных операторов, однако задача лабораторной работы познакомить вас с разнообразием возможностей PostgreSQL, поэтому их использование необходимо.

№ варианта

№ запросов

1

1, 11, 21, 31, 41, 51, 61, 71, 81

  1. Вывести ФИО, должности, оклад, номер трудового договора всех преподавателей

Я без понятия, где искать этот номер трудового, поэтому выбрал employments -> contract_number

SELECT p.last_name,

p.first_name,

p.patronymic,

p.current_position,

p.salary,

e.contract_number

FROM

professors p,

employments e

WHERE

p.professor_id = e.professor_id;

  1. Подсчитать количество отличников в каждой группе по каждой дисциплине, включающей в себя слово “Физика”.

SELECT

f.field_name, -- Название дисциплины

f.field_id, -- ID дисциплины

s.students_group_number, -- Номер группы студентов

COUNT(fc.student_id) AS "Otlichniki" -- Количество отличников

FROM

field_comprehensions fc, -- Таблица оценок

students s, -- Таблица студентов

fields f -- Таблица дисциплин

WHERE

s.student_id = fc.student_id -- Сопоставление студентов с их оценками

AND f.field_id = fc.field -- Сопоставление дисциплин с оценками

AND f.field_name LIKE '%Физика%' -- Поиск дисциплин с названием, содержащим "Физика"

AND fc.mark = 5 -- Фильтр для отличников (оценка = 5)

GROUP BY

s.students_group_number, -- Группировка по номеру группы

f.field_id, -- Группировка по ID дисциплины

f.field_name; -- Группировка по названию дисциплины

  1. Вывести ФИО студентов и преподавателей, у которых совпадают фамилии.

Вывести руководителей всех структурных подразделений и название дисциплины, относящееся к этим структурным подразделениям (если они есть, иначе - null). Отсортировать по дисциплине в обратном порядке.

SELECT

s.first_name,

s.patronymic,

s.last_name AS student_last_name, -- Фамилия студента

-- p.professor_id,

p.first_name AS professor_first_name,

p.patronymic AS professor_patronymic,

p.last_name AS professor_last_name, -- Фамилия преподавателя

su.head_of_the_unit, -- Руководитель структурного подразделения

f.field_name -- Название дисциплины

FROM

students s

JOIN professors p

ON s.last_name = p.last_name -- Соединяем по фамилии

LEFT JOIN employments e

ON p.professor_id = e.professor_id -- Соединяем с назначениями/трудоустройством преподавателей

LEFT JOIN structural_units su

ON e.structural_unit_id = su.structural_unit_id -- Привязываем структурные подразделения

LEFT JOIN fields f

ON f.structural_unit_id = su.structural_unit_id -- Привязываем дисциплины к структурным подразделениям

ORDER BY

f.field_name DESC; -- Сортировка по дисциплине в обратном порядке

LEFT JOIN полезен, когда нужно получить все данные из основной (левой) таблицы, даже если в связанной (правой) таблице нет соответствующих данных.

UNION/EXCEPT/INTERSECT

  1. Вывести фамилии всех студентов и преподавателей в (дубли оставить). Отсортировать по фамилии. Добавить столбец, в котором обозначить преподаватель это или студент.

SELECT

last_name,

'Студент' AS category

FROM

students

UNION ALL

SELECT

last_name,

'Преподаватель' AS category

FROM

professors

ORDER BY

last_name; -- Сортировка по фамилии

UNION ALL: Объединяет результаты двух запросов, сохраняя все дубликаты. Если бы вы использовали UNION, то дубликаты были бы удалены.

SELECT для преподавателей: Выбираем фамилии всех преподавателей и добавляем столбец category с значением 'Преподаватель'.

  1. Вывести название всех групп, количество студентов в них, код всех структурных подразделений, к которым привязаны группы и количество групп в них.

SELECT

sg.students_group_number AS group_name, -- Название группы

COUNT(s.student_id) AS student_count, -- Количество студентов в группе

su.structural_unit_id AS unit_code, -- Код структурного подразделения

COUNT(sg.students_group_number) OVER (PARTITION BY su.structural_unit_id) AS group_count -- Количество групп в подразделении

FROM

students_groups sg -- Таблица групп студентов

LEFT JOIN

students s ON s.students_group_number = sg.students_group_number -- Привязка студентов к группам

LEFT JOIN

structural_units su ON sg.structural_unit_id = su.structural_unit_id -- Привязка групп к структурным подразделениям

GROUP BY

sg.students_group_number,

su.structural_unit_id -- Группировка по группе и структурному подразделению

ORDER BY

sg.students_group_number; -- Сортировка по названию группы

Использование OVER позволяет вам делать более сложные анализы данных, не теряя информацию о строках. Вы можете комбинировать аналитические функции с обычными агрегатами, чтобы получить более подробные результаты.

Вложенные запросы

  1. Вывести фамилию, имя студентов и их оценку по дисциплине ‘ Базы Данных’, если она больше средней оценки всех студентов за эту дисциплину.

SELECT

s.last_name,

s.first_name,

fc.mark

FROM

students s

JOIN

field_comprehensions fc ON s.student_id = fc.student_id

JOIN

fields f ON fc.field = f.field_id

WHERE

f.field_name = 'Базы данных'

AND fc.mark > (

SELECT AVG(mark)

FROM field_comprehensions

WHERE field = f.field_id

);

  1. Вывести фамилию, имя, группу и возраст тех студентов, у которых возраст больше среднего по группе. Первой строчкой в каждой группе при выводе должна быть запись – ‘Средний возраст’(для сортировки можно использовать первую букву латинскую ‘C’) + номер группы + средний возраст по группе. Далее должны быть выведены студенты этой группы, чей возраст больше среднего.

WITH avg_age AS (

SELECT

students_group_number,

AVG(EXTRACT(YEAR FROM age(birthday))) AS avg_age

FROM

students

GROUP BY

students_group_number

)

SELECT

'Средний возраст ' || a.students_group_number || ' ' || ROUND(a.avg_age::numeric, 2) AS info,

s.first_name,

s.last_name,

s.students_group_number,

EXTRACT(YEAR FROM age(s.birthday)) AS age

FROM

students s

JOIN

avg_age a ON s.students_group_number = a.students_group_number

WHERE

EXTRACT(YEAR FROM age(s.birthday)) > a.avg_age

UNION ALL

SELECT

'Средний возраст ' || a.students_group_number || ' ' || ROUND(a.avg_age::numeric, 2),

NULL,

NULL,

a.students_group_number,

NULL

FROM

avg_age a

ORDER BY

students_group_number,

age DESC NULLS LAST;

  • CTE (Common Table Expression):

  • С помощью WITH AverageAge AS (...) мы создаем временную таблицу, которая содержит средний возраст студентов по каждой группе.

  • Первый SELECT:

  • Здесь мы формируем строку, представляющую средний возраст в каждой группе. Используем ROUND для округления среднего возраста до двух знаков после запятой.

  • NULL AS first_name, NULL AS last_name, и т.д. — это заполнители, чтобы соответствовать количеству столбцов в объединенном запросе.

  • UNION ALL:

  • Объединяем результаты с результатами второго запроса, который выбирает студентов с возрастом больше среднего по группе.

  • Второй SELECT:

  • Здесь мы выбираем фамилию, имя, номер группы и возраст студентов, чей возраст больше среднего.

  • ORDER BY:

  • Сначала сортируем по номеру группы, затем используем output IS NULL, чтобы строки с 'Средний возраст' шли первыми, а затем сортируем по фамилии

Дополнительные запросы

  1. Вывести номера студенческих билетов студентов, у которых нет ни одной двойки.

SELECT

fc.student_id, -- Номер студенческого билета

COUNT(fc.student_id) AS "Отличники_и_хорошисты" -- Количество оценок >= 3

FROM

field_comprehensions fc -- Таблица оценок

JOIN

students s -- Таблица студентов

ON

s.student_id = fc.student_id -- Сопоставление студентов с их оценками

WHERE

fc.mark >= 3 -- Студенты без двоек (оценки >= 3)

GROUP BY

fc.student_id -- Группировка по студентам

HAVING

COUNT(CASE WHEN fc.mark < 3 THEN 1 END) = 0; -- Условие на отсутствие двоек

 CASE WHEN fc.mark < 3 THEN 1 END: проверяет наличие двоек у каждого студента.

 COUNT(CASE ...): подсчитывает количество двоек.

 HAVING COUNT(...) = 0: выводит только тех студентов, у которых нет ни одной двойки.

  • HAVING COUNT(...) = 0:

  • Условие HAVING применяется после группировки (GROUP BY) и фильтрует результаты. В нашем случае, оно проверяет, что результат подсчёта двоек равен 0, то есть у студента нет оценок ниже 3.

  • JOIN:

  • JOIN — это оператор, который объединяет строки из двух таблиц на основании определённого условия. Есть несколько типов соединений (например, INNER JOIN, LEFT JOIN, RIGHT JOIN), но все они объединяют таблицы на основе связи между ними.

  • ON:

  • Ключевое слово ON указывает условие, по которому будет происходить соединение таблиц.

  • После ON идёт условие сравнения, которое говорит базе данных, каким образом соединять строки из первой и второй таблиц. Обычно это сравнение происходит между столбцами, которые содержат одинаковые значения (например, идентификаторы в двух таблицах).

Соседние файлы в папке 3 лр