
2 / кр3
.docxМИНИСТЕРСТВО НАУКИ И ВЫСШЕГО ОБРАЗОВАНИЯ РОССИЙСКОЙ ФЕДЕРАЦИИ
федеральное государственное автономное образовательное учреждение высшего образования
«САНКТ-ПЕТЕРБУРГСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ
АЭРОКОСМИЧЕСКОГО ПРИБОРОСТРОЕНИЯ»
Кафедра 41
ПРЕПОДАВАТЕЛЬ
Доцент, канд. техн. наук |
|
|
|
Е. Л. Турнецкая |
должность, уч. степень, звание |
|
подпись, дата |
|
инициалы, фамилия |
Контрольная работа №3
Связь СУБД PostgreSQL и Python.
по курсу: Базы данных
СТУДЕНТКА ГР. № |
Z0411 |
|
25.01.24 |
|
М. В. Карелина |
|
|
номер группы |
|
подпись, дата |
|
инициалы, фамилия |
Номер студенческого билета: 2020/3477
Санкт-Петербург
2024
Цель работы: произвести связь базы данных в PostgreSQL и Python, изучить операции по манипулированию с данными БД, а также созданию простейших пользовательских функций.
Порядок выполнения работы:
1. Использовать БД, созданную в предыдущей ЛР (employees, departments, jobs). Обязательно предоставить схему данных в отчете.
2. Осуществить связь Python и БД в PostgreSQL.
3. Создать новую таблицу locations, по примеру методических указаний. Заполнить таблицу данными:
INSERT INTO locations VALUES ( 1,'Roma', '00989');
INSERT INTO locations VALUES ( 2,'Venice','10934');
INSERT INTO locations VALUES ( 3,'Tokyo', '1689');
INSERT INTO locations VALUES ( 4,'Hiroshima','6823');
INSERT INTO locations VALUES ( 5,'Southlake', '26192');
INSERT INTO locations VALUES ( 6,'South San Francisco', '99236');
INSERT INTO locations VALUES ( 7,'South Brunswick','50090');
INSERT INTO locations VALUES ( 8,'Seattle','98199');
INSERT INTO locations VALUES ( 9,'Toronto','M5V 2L7',);
INSERT INTO locations VALUES ( 10,'Whitehorse','YSW 9T2');
4. Добавить в таблицу с сотрудниками location_id, добавить связь с таблицей locations, заполнить столбец location_id данными. В отчете описать, каким способом было выполнено задание, приложить скриншоты результатов, в том числе обновленную схему данных.
5. Выполнить 3 запроса SELECT в Python, предоставить скриншоты результатов и текстовое пояснение:
На оценку 5 выполняете запросы по таблице 1 (страница 6 методических указаний). Третий запрос на ваш выбор, но необходимо задействовать новую таблицу locations.
6. Создать функцию select_data в СУБД PostgreSQL (см. Методические указания 4 пункт), продемонстрировать результат работы. Вызвать функцию select_data в Python, продемонстрировать результат. Создать функцию select_data1 в скрипте Python, продемонстрировать результат вызова этой функции в СУБД PostgreSQL.
7. Задание на оценку 5. Если данное задание не выполнено итоговая оценка снижается на 1 балл: Создать собственную пользовательскую функцию в СУБД PostgreSQL, используя более сложные SQL-запросы (например, с применением агрегатных функций и связью нескольких таблиц), продемонстрировать результат работы. Создать эту же функцию через скрипт Python.
8. Выполнить любую визуализацию в Python. Графики должны быть наглядными, график обязательно должен иметь заголовок, подписи к осям, а также отображать показательные значения (например, должность, а не id должности). К полученным графикам необходимо дать пояснения, прокомментировать результаты.
Вариант 7.
В данной работе будет использована БД по работникам компании и схема данных, реализованная в прошлой работе (Рис. 1).
Рисунок 1 - Схема данных hr
Нужно открыть предпочитаемую IDE, в данной работе это PyCharm. Библиотека pandas уже установлена, так что надо установить библиотеку psycopg2 через pip install.
После установки можно установить соединение Python с БД в PostgreSQL.
import pandas as pd import psycopg2 # Подключение к базе данных: connection = psycopg2.connect(database="students", # название базы данных user="postgres", password="admin", host="127.0.0.1", port="5432")
Вывод данные о соединении и версии СУБД (Рис. 2):
cursor = connection.cursor() # курсор для выполнения операций с БД print(connection.get_dsn_parameters(), "\n") # вывод свойства соединения cursor.execute("SELECT version();") # выполнение запроса к БД version_ps = cursor.fetchone() # получение результата запроса print("Вы подключены к - ", version_ps, "\n")
Рисунок 2 - Данные о соединении и версии СУБД
Выполнение запрос на выборку данных из таблицы с работами (Рис. 3):
sql = "SELECT * FROM jobs " # запрос SQL df = pd.read_sql_query(sql, connection) print(df)
Рисунок 3 - Результат выполнения SQL запроса
Была создана новая таблица locations.
cursor.execute('''CREATE TABLE if not exists locations (location_id int PRIMARY KEY, city varchar(30), postal_code varchar(12) ); ''')
Проверка, что таблица появилась в СУБД PostgreSQL (Рис. 4):
Рисунок 4 - Создание новой таблицы
Заполнение таблицу данными и выведение результата (Рис. 5):
cursor.execute('''INSERT INTO locations VALUES (1, 'Roma', '00989'), (2,'Venice','10934'), (3,'Tokyo', '1689'), (4,'Hiroshima','6823'), (5,'Southlake', '26192'), (6,'South San Francisco', '99236'), (7,'South Brunswick','50090'), (8,'Seattle','98199'), (9,'Toronto','M5V 2L7'), (10,'Whitehorse','YSW 9T2'); ''') connection.commit() table_locations = pd.read_sql_query("SELECT * FROM locations ", connection) print(table_locations)
Рисунок 5 - Заполненная таблица locations
В таблицу с сотрудниками была добавлена колонка location_id, также была осуществлена связь с таблицей locations и заполнен данными столбец location_id.
cursor.execute('''ALTER TABLE employees ADD COLUMN location_id INTEGER references locations(location_id);''') connection.commit() cursor.execute('''UPDATE employees SET location_id = floor(random() * 10 + 1);''') connection.commit()
Новая схема данных и заполненная таблица employees на Рис. 6.
Рисунок 6 - Схема данных
Теперь необходимо выполнить три запроса SELECT в Python.
Найти сотрудника со второй по счёту минимальной зарплатой. Листинг запроса представлен в листинге 1 и результат на рисунке 7.
Листинг 1: Нахождение сотрудника со второй по счёту минимальной зарплатой
query = ("SELECT e.first_name, e.last_name, e.salary " "FROM hr.employees e " "ORDER BY e.salary " "OFFSET 1 " "LIMIT 1") cursor.execute(query) connection.commit() rows = cursor.fetchall() df = pd.DataFrame(rows, columns=['first_name', 'last_name', 'salary']) print(df)
Рисунок 7 – Результат выполнения запроса
Выяснить, сколько фондовых менеджеров (Stock_manager) работают в отделе
перевозок (Shipping). Листинг запроса представлен в листинге 2 и результат на рисунке 8.
Листинг 2: Выяснить, сколько фондовых менеджеров (Stock_manager) работают в отделе перевозок (Shipping)
query = ("SELECT d.department_name, j.job_title, COUNT(*) AS EmployeesCount " "FROM hr.employees e " "JOIN hr.departments d ON e.department_id = d.department_id " "JOIN hr.jobs j ON e.job_id = j.job_id " "WHERE d.department_name = 'Shipping' AND j.job_title = 'Stock Manager' " "GROUP BY d.department_name, j.job_title") cursor.execute(query) connection.commit() rows = cursor.fetchall() df = pd.DataFrame(rows, columns=['department_name', 'j.job_title', 'EmployeesCount']) print(df)
Рисунок 8 – Результат выполнения запроса
Данный запрос должен быть на наш выбор, но необходимо задействовать новую таблицу locations. Создадим запрос который показывает среднюю зарабротную плату в зависимости от города. Листинг запроса представлен в листинге 3 и результат на рисунке 9.
Листинг 3: Выяснить, среднюю заработную плату в зависимости от города.
create_column_query = "ALTER TABLE locations ADD COLUMN IF NOT EXISTS avg_salary NUMERIC" cursor.execute(create_column_query) connection.commit()
average_salary_query = ("UPDATE locations l " "SET avg_salary = (SELECT AVG(e.salary) " " FROM employees e " " WHERE e.location_id = l.location_id) " "WHERE EXISTS (SELECT 1 FROM employees WHERE location_id = l.location_id)") cursor.execute(average_salary_query) connection.commit() locations_query = "SELECT * FROM locations" cursor.execute(locations_query) rows = cursor.fetchall() locations_df = pd.DataFrame(rows, columns=['location_id','city','postal_code','avg_salary']) # Print the result print(locations_df)
Рисунок 7 - Результат выполнения запроса
Теперь необходимо создать функцию select_data в СУБД PostgreSQL, продемонстрировать результат работы. Вызвать функцию select_data в Python, продемонстрировать результат. Создать функцию select_data1 в скрипте Python, продемонстрировать результат вызова этой функции в СУБД PostgreSQL.
Функция select_data в PostgreSQL на вход получает код отдела и выводит информацию из таблицы departments, фильтруя данные по коду отдела.
CREATE FUNCTION select_data(id_dept int) RETURNS SETOF departments AS $$
SELECT * FROM departments WHERE departments.department_id > id_dept;
$$ LANGUAGE SQL;
SELECT * FROM select_data(30);
Результат вывода в DBeaver (Рис. 10).
Рисунок 10 - Создание функции
Теперь вызов созданной функции из скрипта в Python (Рис. 11):
cursor.callproc('select_data', [20, ]) # вызов функции (название из PostgreSQL) result = cursor.fetchall() # получение результатов result_proc = pd.DataFrame(result) # создание датафрейма с результатом print(result_proc)
Рисунок 11 - Выполнение функции в Python
Теперь необходимо создать функцию select_data1, аналогичную функции выше в скрипте Python и внести изменения в БД в PostgreSQL.
postgresql_func = """ CREATE OR REPLACE FUNCTION select_data1(id_dept int) RETURNS SETOF departments AS $$ SELECT * FROM departments WHERE departments.department_id > id_dept; $$ LANGUAGE SQL; """ cursor.execute(postgresql_func) # выполнение запроса connection.commit() #внесение изменений в БД connection.close() # закрытие соединения cursor.close() # закрытие cursor
Отображение обеих функций в PostgreSQL и вызов функции select_data1 на Рис. 12.
Рисунок 12 – Функция select_data
Теперь необходимо создать пользовательскую функцию. Данная функция показывает суммарную заработную плату в зависимости от введённого номера города. Листинг запроса представлен в листинге 4 и результат на рисунке 13.
Листинг 4: Выяснить, суммарную среднюю заработную плату в зависимости от города.
CREATE OR REPLACE FUNCTION location_salary_sum_with_city(id_loc int)
RETURNS TABLE(location_id int, city text, location_salary_sum double precision) AS $$
SELECT l.location_id, l.city, sum(e.salary)::double precision as location_salary_sum
FROM hr.employees e
JOIN hr.locations l on e.location_id = l.location_id
WHERE e.location_id = id_loc
GROUP BY l.location_id, l.city;
$$ LANGUAGE SQL;
Рисунок 13 - Результат выполнения функции в DBeaver
Код для создания и вызова такой же функции через скрипт Python представлен в листинге 5 и 6. Результат выполнения представлен на рисунке 14.
Листинг 5:
cursor.execute('CREATE OR REPLACE FUNCTION hr.location_salary_sum_with_city1(id_loc int) ' 'RETURNS TABLE(location_id int, city text, location_salary_sum double precision) ' 'AS $$ SELECT l.location_id, l.city, sum(e.salary)::double precision as location_salary_sum ' 'FROM hr.employees e ' 'JOIN hr.locations l on e.location_id = l.location_id ' 'WHERE e.location_id = id_loc ' 'GROUP BY l.location_id, l.city; $$ LANGUAGE SQL;') connection.commit() # внесение изменений в бд connection.close() cursor.close()
Листинг 6:
cursor.callproc('hr.location_salary_sum_with_city1', [5]) result = cursor.fetchall() result_proc = pd.DataFrame(result) print(result_proc) connection.commit() # внесение изменений в бд connection.close() cursor.close()
Рисунок 14 – Результат выполнения функции в Python
Отображение обеих функций в PostgreSQL представлен на рисунке 15.
Рисунок 15 - Функции
На финальном этапе необходимо провести визуализацию средствами Python.
Код визуализации запроса сравнения средней зарплаты по городам представлен в листинге 7, результат визуализации представлен на рисунке 16.
Листинг 7: Сравнения средней зарплаты по городам
query = """ SELECT city, avg_salary FROM locations; """ # Выполнение SQL-запроса cursor.execute(query) # Получение результатов results = cursor.fetchall() # Создание DataFrame с результатами df = pd.DataFrame(results, columns=['Город', 'Средняя зарплата']) # Закрытие курсора и соединения cursor.close() connection.close() # Построение графика plt.figure(figsize=(10, 6)) plt.bar(df['Город'], df['Средняя зарплата']) plt.xlabel('Город') plt.ylabel('Средняя зарплата') plt.title('Средняя зарплата по городам') plt.xticks(rotation=45) plt.tight_layout() plt.show()
Рисунок 16 – Результат запроса с визуализацией
Вывод
В результате выполнения лабораторной работы была создана и заполнена новая таблица locations, добавлен новый столбец location_id в таблицу employees и установлена связь между таблицами employees и locations используя скрипт Python. Также было написано три запроса по заданию и создано четыре функции используя менеджер баз данных и Python. И в итоге выполнена визуализация запроса для базы данных students.