Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
249 changes: 249 additions & 0 deletions lab_11.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,249 @@
--Лабораторная 11.

-- Задание 1. Основы языка pl/pgSQL

-- 1. Напишите анонимный блок для вывода элементов из двумерного массива.
-- Для этого объявите переменную и передайте ей двумерный массив
-- ARRAY[ARRAY[ 10, 20, 30], ARRAY[100,200,300]]
-- В исполняемой секции блока (BEGIN … END) с помощью цикла
-- организуйте поэлементный вывод

do $$
declare
a integer[][];
i integer;
j integer;

begin
a := array[
array[10, 20, 30],
array[100, 200, 300]
];

for i in array_lower(a, 1)..array_upper(a, 1) loop
for j in array_lower(a, 2)..array_upper(a, 2) loop
raise notice 'a[%,%] = %', i, j, a[i][j];
end loop;
end loop;
end;
$$ language plpgsql;

-- 2. C помощью средств pl\pgsql, напишите анонимный блок,
-- выводящий следующие сообщения:
do $$
declare
i int;
j int;
line text;
begin
for i in 1..5 loop
line := '';
for j in 1..i loop
line := line || j || ' ';
end loop;
raise notice 'NOTICE: %', trim(line);
end loop;

for i in 1..5 loop
line := '';
for j in 1..(6 - i) loop
line := line || j || ' ';
end loop;
raise notice 'NOTICE: %', trim(line);
end loop;
end;
$$ language plpgsql;

-- 3. Напишите анонимный блок, который подсчитывает сколько требуется
-- работать в компании, чтобы получать 6-ти значную зарплату. Стартовая
-- зарплата 500$ каждый год рост 10%. Вывести сообщение:
-- «Имея стартовую зарплату [зарплата], надо работать [кол-во лет] лет,
-- чтобы достичь 6-тизначных цифр: [конечная зарплата].».

do $$
declare
start_salary numeric := 500;
current_salary numeric := start_salary;
years int := 0;
begin
while current_salary < 100000 loop
current_salary := current_salary * 1.1;
years := years + 1;
end loop;

raise notice
'имея стартовую зарплату %, надо работать % лет, чтобы достичь 6-тизначных цифр: %.',
start_salary, years, current_salary::numeric(10,3);
end;
$$ language plpgsql;

-- Задание 2. Создание функций и процедур на языке SQL

-- 1. Создайте скалярную функцию. Функция должна принимать произвольную дату
-- и возвращать количество дней между полученной датой и текущей датой.
-- Протестируйте созданную функцию. Приведите код
create function schema2.days_between_today(p_date date)
returns integer
language sql
as
$$
select (current_date - p_date)::int;
$$;

select schema2.days_between_today(date '2025-09-11');

select schema2.days_between_today(current_date);

-- 2. Создайте функцию. Функция должна принимать название города, а возвращать
-- список подразделений, расположенных в указанном городе, и количество сотрудников
-- в этих подразделениях.
-- Протестируйте созданную функцию. Приведите код


create or replace function schema2.get_departments_by_city(p_city text)
returns table (
department_name text,
employees_count int
)
language sql
as
$$
select
d.department_id,
count(e.employee_id) as employees_count
from schema1.departments d
join schema1.locations a
on d.location_id = a.location_id
left join schema1.employees e
on e.department_id = d.department_id
where a.city = p_city
group by d.department_id
order by d.department_id;
$$;


insert into schema1.locations (location_id, street_address, postal_code, city, country_id)
values
(14, 'вшэ', '0001', 'paris',
(select country_id from schema1.countries where country_name = 'France')),
(15, 'сбпгу', '0102', 'gamburg',
(select country_id from schema1.countries where country_name = 'Germany')),
(13, 'чето1', '1142', 'tokyo',
(select country_id from schema1.countries where country_name = 'Japan'));

insert into schema1.departments (department_id,department_name,manager_id, location_id) values
(10,'DEP1',14,14),(2,'DEP2',5,15);

insert into schema1.employees
(employee_id, first_name, last_name, email, hire_date, job_id, department_id)
values
(100, 'John', 'Doe', 'john@paris.com', current_date, 'DEV1', 10);


select *
from schema2.get_departments_by_city('paris');
-- работает (я там что-то когда-то удалял видимо, пришлось добавить)

-- 3. Создайте функцию. Функция должна принимать идентификатор должности, а
-- возвращать название должности и количество сотрудников, занимающих эту должность.
-- Протестируйте созданную функцию. Приведите код

create function schema2.get_employees_by_job(p_job_id varchar)
returns table (
job_title text,
employees_count int
)
language sql
as
$$
select
j.job_title,
count(e.employee_id) as employees_count
from schema1.jobs j
left join schema1.employees e
on e.job_id = j.job_id
where j.job_id = p_job_id
group by j.job_id;
$$;

select *
from schema2.get_employees_by_job('DEV1');

-- 4. Создайте процедуру для добавления новой должности в БД.
create procedure schema2.add_job(
p_job_id varchar,
p_job_title text,
p_min_salary numeric,
p_max_salary numeric
)
language sql
as
$$
insert into schema1.jobs (job_id, job_title, min_salary, max_salary)
values (p_job_id, p_job_title, p_min_salary, p_max_salary);
$$;

call schema2.add_job('dev', 'middle developer', 500, 1500);

select *
from schema1.jobs
where job_id = 'dev';

-- 5. Создайте в вашей БД 2 таблицы: таблицу пользователей users и таблицу
-- друзей пользователей friend
create table public.users (
user_id serial4 not null primary key,
user_name text,
user_added timestamptz
);

create table public.friends (
user_id int4 not null,
friend_user_id int4 not null,
primary key (user_id, friend_user_id),
foreign key (user_id) references public.users(user_id),
foreign key (friend_user_id) references public.users(user_id)
);

-- a. Заполните таблицы данными
insert into public.users (user_name, user_added)
values
('даня', now()),
('ваня', now()),
('борис', now()),
('саша', now()),
('катя', now()),
('миша', now());

insert into public.friends (user_id, friend_user_id)
values
(1, 2),
(1, 4),
(2, 3),
(4, 6),
(5, 1),
(6, 2);

select * from public.friends;

-- b. Создайте функцию, которая будет принимать номер пользователя, а
-- выводить идентификатор пользователя и массив всех его друзей
create function public.get_user_friends(p_user_id int)
returns table (
user_id int,
friends int[]
)
language plpgsql
as
$$
begin
return query
select
p_user_id as user_id,
array_agg(f.friend_user_id order by f.friend_user_id) as friends
from public.friends f
where f.user_id = p_user_id;
end;
$$;

select * from public.get_user_friends(4);