
всем здарова / задания лаб / 2 лр / бд2
.docxПрактическая часть
Вариант к практической части выбирается по формуле: V = (N % 10) +1, где N – номер в списке группы, % - остаток от деления.
Задание 1
Исследование типов данных
Предположим, что в магазине новый конструктор стоит 999 рублей и 99 копеек. Студент С. решил приобрести для дальнейшей перепродажи 100000 таких товаров. Для расчета общей суммы, которую необходимо заплатить был создан следующий скрипт на языке PL/pgSQL. Более подробно о нём будет рассказано в одной из следующих лабораторных работ. Обратите внимание, что значение суммы имеет тип real.
DO
$$
DECLARE
summ real :=0.0;
BEGIN
FOR i IN 1..100000 LOOP
summ := summ + 999.99;
END LOOP;
RAISE NOTICE 'Summ = %;', summ;
--RAISE NOTICE 'Diff = %;', 99999000.00 - summ;
END
$$ language plpgsql;
Запустите скрипт. Раскомментируйте строку с вычислением разницы и определите, сколько денег переплатил студент С? Объясните полученный результат. Измените тип суммы на numeric и money. Какой результат был получен в обоих случаях?
ключевое слово DECLARE используется для объявления курсора внутри блока PL/pgSQL (например, в функции или процедуре). Курсор позволяет управлять набором данных, извлекаемым из таблиц, по одной строке за раз, вместо получения всех строк сразу.
DECLARE используется для объявления переменной summ, которая будет хранить промежуточные результаты сложения.
RAISE NOTICE 'Summ = %;', summ;:
Команда RAISE NOTICE выводит промежуточный результат на экран или в лог. В данном случае выводится итоговая сумма summ, которая вычисляется после завершения цикла.
Этот скрипт выполняет простое сложение чисел в цикле 100 000 раз, прибавляя к переменной summ число 999.99 на каждой итерации. Однако точность вычислений зависит от типа данных, используемого для переменной summ. В изначальном варианте тип данных real может вызывать погрешности из-за ограничения точности представления чисел с плавающей запятой.
Видим, что это экпоненциальное отображение числа (т.е 9,999999 * 10^7)
Достаточно неточно
DIFF – те ушел в минус на 992 условных едениц (переплата)
Тип numeric указывает, что переплаты нет (нет погрешности)
Изменил тип данных на money и у цифр на ::money, а также добавил запятые т.к это денежный тип данных (переплаты тоже нет), а также вывод данных приятнее. (погрешности нет)
Вывод:
real может привести к ошибкам из-за округления.
numeric предоставляет точные результаты.
money работает с округлением и обеспечивает удобство для финансовых операций, но точность может быть ниже, чем у numeric.
Задание 2
Написание запросов на языке SQL
Вар 1 |
1, 11, 21, 31, 41, 51, 61, 71 |
Напишите SQL запросы к учебной базе данных в соответствии с вариантом. Запросы брать из сборник запросов к учебной базе данных, расположенного ниже
Сборник запросов к учебной базе данных
Условия WHERE, ORDER BY
Вывести всех студентов группы отсортировав по возрасту
SELECT students_group_number,age (CURRENT_DATE,birthday),last_name,first_name,patronymic
FROM students
WHERE students_group_number = 'ИВТ-43'
ORDER BY age ASC; -- sortirovka po vozrast up
--AND last_name LIKE '%'
--AND patronymic LIKE '%'
--AND first_name LIKE '%';
Вывести список всех предметов, отсортировав по уникальному Id
SELECT field_id, field_name
FROM fields
GROUP BY field_id – можно было написать просто WHERE field_id LIKE ‘%’
ORDER BY field_id ASC;
Решил по возрастанию ( с 0 – до Z)
Группировка GROUP BY
Подсчитать количество двоечников, троечников, хорошистов и отличников среди студентов.
Именно по предмету! Всего 24999 студента
и сумма сходится
SELECT
CASE
WHEN mark =2 THEN 'Двоечники'
WHEN mark =3 THEN 'Троечники'
WHEN mark =4 THEN 'Хорошисты'
WHEN mark =5 THEN 'Отличники'
END AS категория,
COUNT(*) AS количество_студентов
FROM field_comprehensions -- таблица с оценками
GROUP BY
CASE
WHEN mark =2 THEN 'Двоечники'
WHEN mark =3 THEN 'Троечники'
WHEN mark =4 THEN 'Хорошисты'
WHEN mark =5 THEN 'Отличники'
END;
Подсчитать количество должников по каждой дисциплине и вывести на экран код дисциплины и количество должников, превышающих 50 человек.
Я так понял, что debtor_students
(задание некоректно) или же
field_comprehensions
(сделаю по второму файлу, где долг у тех,
кто не пришел на экз и те у кого 2)
SELECT field,COUNT(*) AS kolvo_dolg
FROM field_comprehensions
WHERE mark <3
GROUP BY field
HAVING COUNT(*) > 50; -- POKAZ GDE >50
Регулярные выражения
Вывести весь 3-й курс ИБ, отсортировать по возрасту
SELECT *, age(CURRENT_DATE,birthday)
FROM students
WHERE students_group_number LIKE 'ИБ-3%'
ORDER BY age ASC;
Вывести всех студентов, родившихся зимой, используя регулярные выражения
SELECT *
FROM students
WHERE TO_CHAR(birthday, 'MM') ~ '^(01|02|12)$';
TO_CHAR(birthday, 'MM') — преобразует дату в строку, которая содержит только месяц в формате двух цифр (MM).
~ '^(01|02|12)$' — регулярное выражение, которое проверяет, соответствует ли месяц значениям "01" (январь), "02" (февраль) или "12" (декабрь).
Общее
Выведите фамилии и количество их повторений, которые начинаются на ту же
букву, что и ваша фамилия, а две последние буквы фамилии с вашей не совпадают.
SELECT last_name, COUNT(*) AS count
FROM students
WHERE last_name LIKE 'Б%'
AND last_name NOT LIKE '%ов'
GROUP BY last_name;
Подсчитать количество студентов, родившихся раньше '01/01/2004' в каждой группе, вывести названия и количество студентов тех групп, в которых таких студентов больше 20. Отсортировать по количеству. Всем столбцам дать русские имена.
Раньше НЕ включительно
SELECT students_group_number AS группа,COUNT(*) AS колво
FROM students
WHERE TO_CHAR(birthday,'YY')~'^(05|06|07|08|09|1[0-9])$'
GROUP BY students_group_number
HAVING COUNT(*) > 20
ORDER BY колво DESC;
Задание 3
Самостоятельно разработайте 7 осмысленных запросов к базе данных, используя приведенные в данной лабораторной работе материалы.
(колво студентов в группе)
SELECT
students_group_number AS "Номер группы",
COUNT(*) AS "Количество студентов"
FROM
students
GROUP BY
students_group_number
ORDER BY
"Количество студентов" DESC;
(Средняя оценка)
SELECT
field_id AS "Код дисциплины",
AVG(mark) AS "Средняя оценка"
FROM
field_comprehensions
GROUP BY
field_id
ORDER BY
"Средняя оценка" DESC;
(Студенты с оценками ниже 3 по дисциплине 'Математика')
SELECT
student_id AS "ID студента",
mark AS "Оценка"
FROM
field_comprehensions
WHERE
field_id IN (
SELECT field_id
FROM fields
WHERE field_name = 'Математика'
)
AND mark < 3;
Дата рождения студентов, родившихся в зимние месяцы (декабрь, январь, февраль)
SELECT
last_name AS "Фамилия",
first_name AS "Имя",
birthday AS "Дата рождения"
FROM
students
WHERE
TO_CHAR(birthday, 'MM') IN ('12', '01', '02');
Фамилии студентов, имеющих оценки ниже 3 по как минимум одной дисциплине
SELECT DISTINCT
student_id AS "ID студента"
FROM
field_comprehensions
WHERE
mark < 3;
Группы студентов с количеством студентов, родившихся до 1 января 2000 года, превышающим 10 человек
SELECT
students_group_number AS "Номер группы",
COUNT(*) AS "Количество студентов"
FROM
students
WHERE
birthday < '2000-01-01'
GROUP BY
students_group_number
HAVING
COUNT(*) > 10
ORDER BY
"Количество студентов" DESC;
Студенты, не сдавшие ни одну дисциплину (т.е. нет записей в field_comprehensions
SELECT
student_id AS "ID студента"
FROM
students
WHERE
student_id NOT IN (
SELECT DISTINCT student_id
FROM field_comprehensions
);