From 2360cb388fd2e797be9b399706a7920b8747285f Mon Sep 17 00:00:00 2001 From: ada-dmitry Date: Fri, 15 Dec 2023 22:05:50 +0300 Subject: [PATCH] done 7lab --- Lab#7/lab7.sql | 128 ++++++++++++++++++++++++++++++++++++ Lab#7/lab7_aa.sql | 99 ++++++++++++++++++++++++++++ Lab/Lab#6/lab6.sql | 2 +- Lab/Lab#6/lab6_done.sql | 140 ++++++++++++++++------------------------ 4 files changed, 285 insertions(+), 84 deletions(-) create mode 100644 Lab#7/lab7.sql create mode 100644 Lab#7/lab7_aa.sql diff --git a/Lab#7/lab7.sql b/Lab#7/lab7.sql new file mode 100644 index 0000000..238f434 --- /dev/null +++ b/Lab#7/lab7.sql @@ -0,0 +1,128 @@ +-- Лабораторная работа №7 || Антипенко, Дробышевский || Вариант 4 -- + +-- Задание 1 +-- • Создайте две таблицы: people и people_log. Первая таблица должна +-- содержать поля идентификатор (id), имя (first_name), фамилия +-- (last_name), дата рождения (birthday), текущее состояние счёта +-- (amount). Поле id – это первичный ключ. Поле amount – это +-- действительное число. Вторая таблица должна содержать поля: +-- идентификатор человека (person_id) дата операции (operation_date), +-- сумма (sum). Поле person_id должно быть ограничено, как внешний +-- ключ, ссылающийся на поле id таблицы people. Поле operation_date +-- должно позволить сохранять дату и время. Поле sum – это +-- действительное число. Заполните таблицы people и people_log +-- несколькими записями (не менее 5 на таблицу). + + CREATE TABLE people ( + id SERIAL PRIMARY KEY, + first_name VARCHAR(50), + last_name VARCHAR(50), + birthday DATE, + amount DECIMAL(10, 2) + ); + + CREATE TABLE people_log ( + id SERIAL PRIMARY KEY, + person_id INTEGER REFERENCES people(id), + operation_date TIMESTAMP, + sum DECIMAL(10, 2) + ); + + INSERT INTO people (first_name, last_name, birthday, amount) + VALUES + ('Иван', 'Иванов', '1985-05-15', 1000.50), + ('Петр', 'Петров', '1990-10-20', 750.25), + ('Мария', 'Сидорова', '1978-12-03', 3000.75), + ('Елена', 'Козлова', '1989-08-27', 200.00), + ('Алексей', 'Смирнов', '1980-04-18', 1500.00); + + INSERT INTO people_log (person_id, operation_date, sum) + VALUES + (1, '2023-09-20 10:15:00', 250.00), + (3, '2023-10-01 15:30:00', 800.50), + (2, '2023-11-05 08:45:00', 100.25), + (4, '2023-11-25 12:00:00', 50.00), + (5, '2023-12-02 18:20:00', 300.00); + +SELECT * FROM people; +SELECT * FROM people_log; + + +-- Задание 2 +-- • Напишите процедуру или функцию statement_of_acount, которая на +-- основе двух параметров: даты начала периода и даты окончания +-- периода печатала бы на экран данные (operation_date и sum) трёх самых +-- крупных операций с положительной суммой, трёх самых крупных +-- операций с отрицательной суммой и данные об общем числе операций +-- и среднем значении суммы. + +CREATE OR REPLACE PROCEDURE statement_of_acount(start_date DATE, end_date DATE) AS $$ +DECLARE + pos_sum RECORD; + neg_sum RECORD; + total_count INTEGER; + avg_amount NUMERIC; + const CONSTANT INTEGER = 3; + +BEGIN + FOR pos_sum IN ( + SELECT operation_date, sum + FROM people_log + WHERE operation_date BETWEEN start_date AND end_date AND sum > 0 + ORDER BY sum DESC + LIMIT const + ) LOOP + RAISE INFO 'Positive: %, Sum: %', pos_sum.operation_date, pos_sum.sum; + END LOOP; + + FOR neg_sum IN ( + SELECT operation_date, sum + FROM people_log + WHERE operation_date BETWEEN start_date AND end_date AND sum < 0 + ORDER BY sum ASC + LIMIT const + ) LOOP + RAISE INFO 'Negative: %, Sum: %', neg_sum.operation_date, neg_sum.sum; + END LOOP; + + SELECT COUNT(*) INTO total_count + FROM people_log + WHERE operation_date BETWEEN start_date AND end_date; + + SELECT AVG(sum) INTO avg_amount + FROM people_log + WHERE operation_date BETWEEN start_date AND end_date; + + RAISE INFO 'Total number of operations: %', total_count; + RAISE INFO 'Average amount of transactions: %', avg_amount; + +END $$ LANGUAGE plpgsql; + +CALL statement_of_acount('2023-01-01', '2023-12-31'); + + +-- Задание 3 +-- • Напишите процедуру или функцию account_operation, которая на +-- основе двух параметров: идентификатора человека и суммы вносит +-- изменения в таблицы people и people_log. В таблице people у человека с +-- указанным в качестве параметра идентификатором состояние счёта +-- должно измениться на указанную в качестве параметра сумму. В +-- таблицу people_log должна быть добавлена запись с указанным в +-- качестве параметра идентификатором человека, текущей датой и +-- временем и указанной в качестве параметра суммой. + + + +CREATE OR REPLACE PROCEDURE account_operation(new_id integer, add_sum numeric) AS $$ +DECLARE +BEGIN + UPDATE people + SET amount = amount + add_sum + WHERE id = new_id; + INSERT INTO people_log (person_id, operation_date, sum) VALUES (new_id, CURRENT_TIMESTAMP(0), add_sum); +END $$ LANGUAGE plpgsql; + +CALL account_operation(5, 1000000); + +SELECT * FROM people; +SELECT * FROM people_log; \ No newline at end of file diff --git a/Lab#7/lab7_aa.sql b/Lab#7/lab7_aa.sql new file mode 100644 index 0000000..56fe44c --- /dev/null +++ b/Lab#7/lab7_aa.sql @@ -0,0 +1,99 @@ +DROP TABLE people_log IF EXISTS; +DROP TABLE people IF EXISTS; + + +--1-- +CREATE TABLE people ( + id SERIAL PRIMARY KEY, + first_name VARCHAR(64), + last_name VARCHAR(64), + birthday DATE, + amount NUMERIC(10,2) +); + +CREATE TABLE people_log ( + person_id INTEGER REFERENCES people(id), + operation_date TIMESTAMP, + sum NUMERIC(10,2) +); + +INSERT INTO people (first_name, last_name, birthday, amount) +VALUES ('Andrey', 'Ad', '2004-03-09', 1000.00), + ('Sanal', 'Bat', '2004-12-15', 2000.00), + ('Alex', 'Yak', '2004-08-10', 3000.00), + ('Dima', 'Klev', '2004-04-25', 4000.00), + ('David', 'Dav', '2001-11-30', 5000.00), + ('Reno', 'G', '2004-08-28', 6000.00), + ('Ilya', 'Zim', '2005-01-06', 7000.00), + ('Sema', 'Akh', '2005-12-01', 8000.00); + + +INSERT INTO people_log ( person_id, operation_date, sum) +VALUES +(1, '2022-01-05 17:15:00', 100.00), +(2, '2022-01-06 17:30:00', 300.00), +(3, '2022-01-07 17:45:00', 300.00), +(4, '2022-01-08 18:00:00', 400.00), +(5, '2022-01-09 18:15:00', 500.00), +(6, '2022-01-10 17:15:00', -100.00), +(7, '2022-01-12 17:15:00', -400.00), +(8, '2022-01-29 17:15:00', -200.00); + + + +SELECT * FROM people; +SELECT * FROM people_log; + + +--2-- + +CREATE OR REPLACE PROCEDURE statement_of_acount(start_date DATE, end_date DATE) AS $$ +DECLARE + pos_sum RECORD; + neg_sum RECORD; + total_count INTEGER; + avg_amount NUMERIC; +BEGIN + FOR pos_sum IN ( + SELECT operation_date, sum + FROM people_log + WHERE operation_date BETWEEN start_date AND end_date AND sum > 0 + ORDER BY sum DESC + LIMIT 3 + ) LOOP + RAISE INFO 'Положительная операция: %, Сумма: %', pos_sum.operation_date, pos_sum.sum; + END LOOP; + + FOR neg_sum IN ( + SELECT operation_date, sum + FROM people_log + WHERE operation_date BETWEEN start_date AND end_date AND sum < 0 + ORDER BY sum ASC + LIMIT 3 + ) LOOP + RAISE INFO 'Отрицательная операция: %, Сумма: %', neg_sum.operation_date, neg_sum.sum; + END LOOP; + + SELECT COUNT(*) INTO total_count + FROM people_log + WHERE operation_date BETWEEN start_date AND end_date; + + SELECT AVG(sum) INTO avg_amount + FROM people_log + WHERE operation_date BETWEEN start_date AND end_date; + + RAISE INFO 'Общее количество операций: %', total_count; + RAISE INFO 'Средняя сумма операций: %', avg_amount; + +END $$ LANGUAGE plpgsql; +CALL statement_of_acount('2022-01-01', '2022-11-12'); + +--3-- +CREATE OR REPLACE PROCEDURE account_operation(new_id integer, summa numeric) AS $$ +DECLARE +BEGIN + UPDATE people SET amount = amount + summa WHERE id = new_id; + INSERT INTO people_log (person_id, operation_date, sum) VALUES (new_id, CURRENT_TIMESTAMP(0), summa); +END $$ LANGUAGE plpgsql; + +CALL account_operation(1, 100); \ No newline at end of file diff --git a/Lab/Lab#6/lab6.sql b/Lab/Lab#6/lab6.sql index 06a1c72..86a98ee 100644 --- a/Lab/Lab#6/lab6.sql +++ b/Lab/Lab#6/lab6.sql @@ -33,7 +33,7 @@ BEGIN ORDER BY salary_in_euro LIMIT 10 ), highest_salary AS ( - SELECT max(salary_in_euro) AS max_salary + SELECT max(salary_in_euro) AS max_salary FROM bd6_employees ) UPDATE bd6_employees e diff --git a/Lab/Lab#6/lab6_done.sql b/Lab/Lab#6/lab6_done.sql index bf74e70..d3bb14e 100644 --- a/Lab/Lab#6/lab6_done.sql +++ b/Lab/Lab#6/lab6_done.sql @@ -9,41 +9,23 @@ b) Напишите программу на языке PL/SQL, печатающ и имя сотрудника с идентификатором 1 и всех его подчинённых, как прямых, так и подчинённых более низкого ранга. */ --- CREATE OR REPLACE PROCEDURE department_names() AS $$ --- DECLARE d_attrs RECORD; --- BEGIN - --- FOR d_attrs IN WITH RECURSIVE tmp AS ( --- SELECT id, first_name, last_name, manager_id, 1 AS level --- FROM bd6_employees --- WHERE manager_id = 1 or id = 1 --- UNION ALL --- SELECT e.id, e.first_name, e.last_name, e.manager_id, t.level + 1 --- FROM bd6_employees e JOIN tmp t ON e.manager_id = t.id ) - --- SELECT * FROM tmp --- LOOP --- RAISE INFO ' % % ', d_attrs.first_name, d_attrs.last_name; --- END LOOP; --- END $$ LANGUAGE plpgsql; --- CALL department_names(); - -- Пункт а) WITH RECURSIVE tmp AS ( - SELECT id, first_name, last_name, manager_id, 1 AS level - FROM bd6_employees - WHERE manager_id = 1 OR id = 1 - UNION ALL - SELECT e.id, e.first_name, e.last_name, e.manager_id, t.level + 1 + + SELECT id, first_name, last_name, manager_id, 1 AS level + FROM bd6_employees + WHERE id = 1 + UNION all + SELECT e.id, e.first_name, e.last_name, e.manager_id, t.level + 1 FROM bd6_employees e - JOIN tmp t ON e.manager_id = t.id + JOIN tmp t ON e.manager_id = t.id ) -SELECT id, first_name, last_name +SELECT * FROM tmp -GROUP BY id, first_name, last_name; +; -- Пункт б) -CREATE OR REPLACE PROCEDURE department_names(integer) AS $$ +CREATE OR REPLACE PROCEDURE depa(integer) AS $$ DECLARE d_attrs RECORD; i integer; @@ -59,13 +41,12 @@ FOR d_attrs IN IF d_attrs.manager_id=$1 THEN RAISE INFO ' % % % % ', d_attrs.first_name, d_attrs.last_name, d_attrs.id, d_attrs.manager_id; l:= d_attrs.id; - CALL department_names(l); + CALL depa(l); END IF; END LOOP; END $$ LANGUAGE plpgsql; - -CREATE OR REPLACE PROCEDURE department_names2(integer) AS $$ +CREATE OR REPLACE PROCEDURE dep(integer) AS $$ DECLARE d_attrs RECORD; BEGIN @@ -85,10 +66,9 @@ DECLARE RAISE INFO ' % % % % ', d_attrs.first_name, d_attrs.last_name, d_attrs.id, d_attrs.manager_id; END IF; END LOOP; -CALL department_names($1); +CALL depa($1); END $$ LANGUAGE plpgsql; -CALL department_names2(4); - +CALL dep(1); -- Task 2 -- /* Напишите программу на языке PL/SQL, выбирающую строки из таблицы @@ -100,6 +80,8 @@ employees в порядке возрастания заработной плат увеличивается на остаток от округления, полученный от предыдущего сотрудника, а затем округляется до сотен в меньшую сторону. */ +UPDATE bd6_employees SET salary_in_euro = 299 WHERE id = 3; + CREATE OR REPLACE PROCEDURE print_employees() AS $$ DECLARE current_salary INTEGER; @@ -107,52 +89,28 @@ m_salary INTEGER; mod_salary INTEGER := 0; employee_rec RECORD; BEGIN -FOR employee_rec IN ( +FOR employee_rec IN + ( SELECT last_name, first_name, salary_in_euro FROM bd6_employees - ORDER BY salary_in_euro) + ORDER BY salary_in_euro + ) LOOP - current_salary := employee_rec.salary_in_euro; - - IF mod_salary=0 THEN - m_salary := (current_salary / 100) * 100; - ELSE - m_salary := ((current_salary + mod_salary) / 100) * 100; -END IF; + current_salary := employee_rec.salary_in_euro; + + m_salary := ((current_salary + mod_salary) / 100) * 100; RAISE NOTICE 'Employee: % % || Modified Salary: %', employee_rec.last_name, employee_rec.first_name, m_salary; +mod_salary := mod(current_salary + mod_salary,100); END LOOP; END $$ LANGUAGE plpgsql; CALL print_employees(); -CREATE OR REPLACE PROCEDURE print_employees() AS $$ -DECLARE -current_salary INTEGER; -m_salary INTEGER; -mod_salary INTEGER := 0; -employee_rec RECORD; -BEGIN -FOR employee_rec IN ( - SELECT last_name, first_name, salary_in_euro - FROM bd6_employees - ORDER BY salary_in_euro) +SELECT * +FROM bd6_employees +ORDER BY salary_in_euro; -LOOP - current_salary := employee_rec.salary_in_euro; - - IF mod_salary=0 THEN - m_salary := (current_salary / 100) * 100; - ELSE - m_salary := ((current_salary + mod_salary) / 100) * 100; -END IF; - -RAISE NOTICE 'Employee: % %, Modified Salary: %', employee_rec.last_name, employee_rec.first_name, m_salary; -mod_salary := current_salary - m_salary; -END LOOP; -END $$ LANGUAGE plpgsql; - -CALL print_employees(); -- Task 3 -- /* Напишите программу на языке PL/SQL, удаляющую 10 сотрудников с @@ -167,7 +125,7 @@ DECLARE salaries RECORD; small NUMERIC[]; larg NUMERIC[]; - const CONSTANT INTEGER = 10; + const CONSTANT INTEGER = 3; BEGIN FOR salaries IN SELECT id, salary_in_euro @@ -242,26 +200,42 @@ SELECT * FROM dep_staff_counts; -CREATE OR REPLACE PROCEDURE department_names(integer) AS $$DECLARE d_attrs RECORD; -i integer;l integer; +CREATE OR REPLACE PROCEDURE department_names(integer) AS $$ +DECLARE + d_attrs RECORD; + i INTEGER; + l INTEGER; BEGIN -FOR d_attrs IN ( SELECT id,last_name, first_name, manager_id - FROM bd6_employees order by manager_id ) - LOOP - if d_attrs.manager_id=$1 then - RAISE INFO ' % % % % ', d_attrs.first_name, d_attrs.last_name, d_attrs.id, d_attrs.manager_id; l:= d_attrs.id; - call department_names(l); end if; +FOR d_attrs IN + ( + SELECT id,last_name, first_name, manager_id + FROM bd6_employees order by manager_id + ) + LOOP + IF d_attrs.manager_id=$1 THEN + RAISE INFO ' % % % % ', d_attrs.first_name, d_attrs.last_name, d_attrs.id, d_attrs.manager_id; + l:= d_attrs.id; + CALL department_names(l); + END IF; END LOOP; END $$ LANGUAGE plpgsql; CREATE OR REPLACE PROCEDURE department_names2(integer) AS $$ DECLARE d_attrs RECORD; -BEGINFOR d_attrs IN ( - SELECT id,last_name, first_name, manager_id FROM bd6_employees order by manager_id ) +BEGIN + FOR d_attrs IN + ( + SELECT id,last_name, first_name, manager_id + FROM bd6_employees + order by manager_id + ) LOOP - if d_attrs.id=$1 then RAISE INFO ' % % % % ', d_attrs.first_name, d_attrs.last_name, d_attrs.id, d_attrs.manager_id; - end if;END LOOP; -CALL department_names($1);END $$ LANGUAGE plpgsql; + if d_attrs.id=$1 then + RAISE INFO ' % % % % ', d_attrs.first_name, d_attrs.last_name, d_attrs.id, d_attrs.manager_id; + end if; + END LOOP; +CALL department_names($1); +END $$ LANGUAGE plpgsql; CALL department_names2(4); \ No newline at end of file