diff --git a/homework-1/create_tables.sql b/homework-1/create_tables.sql index 2240c4efb..9bedc58bb 100644 --- a/homework-1/create_tables.sql +++ b/homework-1/create_tables.sql @@ -1 +1,30 @@ -- SQL-команды для создания таблиц +CREATE TABLE customers +( + customer_id text PRIMARY KEY, + company_name text, + contact_name text +); + +CREATE TABLE employees +( + employee_id int PRIMARY KEY, + first_name text, + last_text text, + title text, + birth_date text, + notes text +); + +CREATE TABLE orders +( + order_id int PRIMARY KEY, + customer_id text REFERENCES customers(customer_id), + employee_id int REFERENCES employees(employee_id), + order_date text, + ship_city text +); + +SELECT * FROM customers +SELECT * FROM employees +SELECT * FROM orders diff --git a/homework-1/main.py b/homework-1/main.py index 5b5e8ffd4..445285c01 100644 --- a/homework-1/main.py +++ b/homework-1/main.py @@ -1 +1,30 @@ -"""Скрипт для заполнения данными таблиц в БД Postgres.""" +import csv +import psycopg2 + +conn_params = { + "host": "localhost", + "database": "north", + "user": "postgres", + "password": "catonnameG@v1" +} + + +def insert_table(params, url, table): + """ + Функция для заполнения таблиц в PostgresSQL + """ + with psycopg2.connect(**params) as conn: + with conn.cursor() as cur: + with open(url, newline='') as file: + csv_file = csv.reader(file) + i = 0 + for row in csv_file: + arguments = '%s, ' * (len(row) - 1) + '%s' + if i != 0: # Для пропуска первой строки(оглавления) в файле csv + cur.execute(f"INSERT INTO {table} VALUES ({arguments})", row) + i += 1 + + +insert_table(conn_params, 'north_data/customers_data.csv', 'customers') +insert_table(conn_params, 'north_data/employees_data.csv', 'employees') +insert_table(conn_params, 'north_data/orders_data.csv', 'orders') diff --git a/homework-2/filter_sorting.sql b/homework-2/filter_sorting.sql index 3c23694e7..8538760b6 100644 --- a/homework-2/filter_sorting.sql +++ b/homework-2/filter_sorting.sql @@ -1,14 +1,24 @@ -- Напишите запросы, которые выводят следующую информацию: -- 1. заказы, доставленные в страны France, Germany, Spain (таблица orders, колонка ship_country) -SELECT ... +SELECT * FROM orders +WHERE ship_country in ('France', 'Germany', 'Spain') -- 2. уникальные страны и города, куда отправлялись заказы, отсортировать по странам и городам (таблица orders, колонки ship_country, ship_city) - +SELECT DISTINCT ship_country, ship_city +FROM orders +ORDER BY ship_country, ship_city -- 3. сколько дней в среднем уходит на доставку товара в Германию (таблица orders, колонки order_date, shipped_date, ship_country) - +SELECT AVG(shipped_date - order_date) +FROM orders +WHERE ship_country = 'Germany' -- 4. минимальную и максимальную цену среди продуктов, не снятых с продажи (таблица products, колонки unit_price, discontinued не равно 1) - +SELECT min(unit_price), max(unit_price) +FROM products +WHERE discontinued <> 1 -- 5. минимальную и максимальную цену среди продуктов, не снятых с продажи и которых имеется не меньше 20 (таблица products, колонки unit_price, units_in_stock, discontinued не равно 1) +SELECT min(unit_price), max(unit_price) +FROM products +WHERE discontinued <> 1 and units_in_stock > 20 diff --git a/homework-2/groupby.sql b/homework-2/groupby.sql index bc77259e5..b43789b38 100644 --- a/homework-2/groupby.sql +++ b/homework-2/groupby.sql @@ -1,20 +1,45 @@ -- Напишите запросы, которые выводят следующую информацию: -- 1. заказы, отправленные в города, заканчивающиеся на 'burg'. Вывести без повторений две колонки (город, страна) (см. таблица orders, колонки ship_city, ship_country) - +SELECT DISTINCT ship_city, ship_country +FROM orders +WHERE ship_city LIKE '%burg' -- 2. из таблицы orders идентификатор заказа, идентификатор заказчика, вес и страну отгрузки. Заказ отгружен в страны, начинающиеся на 'P'. Результат отсортирован по весу (по убыванию). Вывести первые 10 записей. - +SELECT order_id, customer_id, freight, ship_country +FROM orders +WHERE ship_country LIKE 'P%' +ORDER BY freight DESC +LIMIT 10 -- 3. имя, фамилию и телефон сотрудников, у которых в данных отсутствует регион (см таблицу employees) - +SELECT first_name, last_name, home_phone +FROM employees +WHERE region IS NULL -- 4. количество поставщиков (suppliers) в каждой из стран. Результат отсортировать по убыванию количества поставщиков в стране - +SELECT country, COUNT(*) +FROM suppliers +GROUP BY country +ORDER BY COUNT(*) DESC -- 5. суммарный вес заказов (в которых известен регион) по странам, но вывести только те результаты, где суммарный вес на страну больше 2750. Отсортировать по убыванию суммарного веса (см таблицу orders, колонки ship_region, ship_country, freight) - +SELECT ship_country, SUM(freight) +FROM orders +WHERE ship_region IS NOT NULL +GROUP BY ship_country +HAVING SUM(freight) > 2750 +ORDER BY SUM(freight) DESC -- 6. страны, в которых зарегистрированы и заказчики (customers) и поставщики (suppliers) и работники (employees). - +SELECT country FROM customers +INTERSECT +SELECT country FROM employees +INTERSECT +SELECT country FROM suppliers -- 7. страны, в которых зарегистрированы и заказчики (customers) и поставщики (suppliers), но не зарегистрированы работники (employees). +SELECT country FROM customers +INTERSECT +SELECT country FROM suppliers +EXCEPT +SELECT country FROM employees diff --git a/homework-2/simple_queries.sql b/homework-2/simple_queries.sql index 0844a9131..615ab2198 100644 --- a/homework-2/simple_queries.sql +++ b/homework-2/simple_queries.sql @@ -1,14 +1,20 @@ -- Напишите запросы, которые выводят следующую информацию: -- 1. "имя контакта" и "город" (contact_name, city) из таблицы customers (только эти две колонки) -SELECT ... +SELECT contact_name, city +FROM customers -- 2. идентификатор заказа и разницу между датами формирования (order_date) заказа и его отгрузкой (shipped_date) из таблицы orders - +SELECT order_id, (shipped_date - order_date) +FROM orders -- 3. все города без повторов, в которых зарегистрированы заказчики (customers) - +SELECT DISTINCT city +FROM customers -- 4. количество заказов (таблица orders) - +SELECT COUNT(*) +FROM orders -- 5. количество стран, в которые отгружался товар (таблица orders, колонка ship_country) +SELECT COUNT(DISTINCT ship_country) +FROM orders diff --git a/homework-3/queries.sql b/homework-3/queries.sql index 5f2b4173b..06bf99b70 100644 --- a/homework-3/queries.sql +++ b/homework-3/queries.sql @@ -1,16 +1,32 @@ -- Напишите запросы, которые выводят следующую информацию: -- 1. Название компании заказчика (company_name из табл. customers) и ФИО сотрудника, работающего над заказом этой компании (см таблицу employees), -- когда и заказчик и сотрудник зарегистрированы в городе London, а доставку заказа ведет компания United Package (company_name в табл shippers) - +SELECT customers.company_name AS customer, CONCAT(first_name, ' ', last_name) AS employee +FROM orders +INNER JOIN customers ON customers.customer_id=orders.customer_id +INNER JOIN employees ON employees.employee_id=orders.employee_id +INNER JOIN shippers ON shippers.shipper_id=orders.ship_via +WHERE customers.city=employees.city and customers.city='London' and shippers.company_name='United Package' -- 2. Наименование продукта, количество товара (product_name и units_in_stock в табл products), -- имя поставщика и его телефон (contact_name и phone в табл suppliers) для таких продуктов, -- которые не сняты с продажи (поле discontinued) и которых меньше 25 и которые в категориях Dairy Products и Condiments. -- Отсортировать результат по возрастанию количества оставшегося товара. - +SELECT products.product_name, products.units_in_stock, suppliers.contact_name, suppliers.phone +FROM products +INNER JOIN suppliers USING(supplier_id) +INNER JOIN categories USING(category_id) +WHERE discontinued = 0 and units_in_stock < 25 and categories.category_id IN ( + SELECT category_id FROM categories WHERE category_name IN ('Dairy Products', 'Condiments')) +ORDER BY units_in_stock -- 3. Список компаний заказчиков (company_name из табл customers), не сделавших ни одного заказа - +SELECT company_name +FROM customers +WHERE NOT EXISTS(SELECT * FROM orders WHERE orders.customer_id=customers.customer_id) -- 4. уникальные названия продуктов, которых заказано ровно 10 единиц (количество заказанных единиц см в колонке quantity табл order_details) -- Этот запрос написать именно с использованием подзапроса. +SELECT DISTINCT product_name +FROM products +WHERE product_id IN (SELECT product_id FROM order_details WHERE quantity = 10) diff --git a/homework-4/alter_northwind.sql b/homework-4/alter_northwind.sql index 852b12178..61f9d1568 100644 --- a/homework-4/alter_northwind.sql +++ b/homework-4/alter_northwind.sql @@ -1,12 +1,17 @@ -- Подключиться к БД Northwind и сделать следующие изменения: -- 1. Добавить ограничение на поле unit_price таблицы products (цена должна быть больше 0) - +ALTER TABLE products ADD CONSTRAINT chk_products_unit_price CHECK (unit_price>0) -- 2. Добавить ограничение, что поле discontinued таблицы products может содержать только значения 0 или 1 - +ALTER TABLE products ADD CONSTRAINT chk_products_unit_price CHECK (unit_price>0) -- 3. Создать новую таблицу, содержащую все продукты, снятые с продажи (discontinued = 1) - +SELECT * INTO products_discontinued FROM products WHERE discontinued=1 -- 4. Удалить из products товары, снятые с продажи (discontinued = 1) -- Для 4-го пункта может потребоваться удаление ограничения, связанного с foreign_key. Подумайте, как это можно решить, чтобы связь с таблицей order_details все же осталась. +ALTER TABLE order_details DROP CONSTRAINT fk_order_details_products; +DELETE FROM products WHERE discontinued=1; +DELETE FROM order_details WHERE product_id NOT IN ( +SELECT product_id FROM products); +ALTER TABLE order_details ADD CONSTRAINT fk_order_details_products FOREIGN KEY(product_id) REFERENCES products(product_id) diff --git a/homework-4/alter_student.sql b/homework-4/alter_student.sql index d4f099c60..36a08a038 100644 --- a/homework-4/alter_student.sql +++ b/homework-4/alter_student.sql @@ -1,19 +1,29 @@ -- 1. Создать таблицу student с полями student_id serial, first_name varchar, last_name varchar, birthday date, phone varchar - +CREATE TABLE student +( + student_id serial, + first_name varchar, + last_name varchar, + birthday date, + phone varchar +) -- 2. Добавить в таблицу student колонку middle_name varchar - +ALTER TABLE student ADD COLUMN middle_name varchar -- 3. Удалить колонку middle_name - +ALTER TABLE student DROP COLUMN middle_name -- 4. Переименовать колонку birthday в birth_date - +ALTER TABLE student RENAME COLUMN birthday TO birth_day -- 5. Изменить тип данных колонки phone на varchar(32) - +ALTER TABLE student ALTER COLUMN phone SET DATA TYPE varchar(32) -- 6. Вставить три любых записи с автогенерацией идентификатора - +INSERT INTO student (first_name, last_name, birth_day, phone) VALUES ('Fedor', 'Fedorov', '1999-12-30', '99-63-40'); +INSERT INTO student (first_name, last_name, birth_day, phone) VALUES ('Poly', 'Fedorova', '1997-01-11', '99-56-80'); +INSERT INTO student (first_name, last_name, birth_day, phone) VALUES ('Ann', 'Fedora', '2003-03-15', '99-48-91'); -- 7. Удалить все данные из таблицы со сбросом идентификатор в исходное состояние +TRUNCATE TABLE student RESTART IDENTITY diff --git a/homework-5/main.py b/homework-5/main.py index 715c0891b..b25cc637d 100644 --- a/homework-5/main.py +++ b/homework-5/main.py @@ -1,5 +1,5 @@ import json - +import sqlite3 import psycopg2 from config import config @@ -11,6 +11,7 @@ def main(): db_name = 'my_new_db' params = config() + conn = None create_database(params, db_name) @@ -27,6 +28,7 @@ def main(): print("Таблица suppliers успешно создана") suppliers = get_suppliers_data(json_file) + print([sup.get('products') for sup in suppliers]) insert_suppliers_data(cur, suppliers) print("Данные в suppliers успешно добавлены") @@ -42,31 +44,67 @@ def main(): def create_database(params, db_name) -> None: """Создает новую базу данных.""" - pass + + conn = psycopg2.connect(dbname='youtube', **params) + conn.autocommit = True + with conn.cursor() as cur: + cur.execute(f'DROP DATABASE IF EXISTS {db_name}') + with conn.cursor() as cur: + cur.execute(f'CREATE DATABASE {db_name}') + conn.close() + def execute_sql_script(cur, script_file) -> None: """Выполняет скрипт из файла для заполнения БД данными.""" - + with open(script_file, 'r') as file: + file_sql = file.read() + cur.execute(file_sql) def create_suppliers_table(cur) -> None: """Создает таблицу suppliers.""" - pass + cur.execute(""" + CREATE TABLE suppliers ( + suppliers_id SERIAL PRIMARY KEY, + company_name VARCHAR(255), + contact VARCHAR(255), + address VARCHAR(255), + phone TEXT, + fax TEXT, + homepage VARCHAR(255) + ) + """) def get_suppliers_data(json_file: str) -> list[dict]: """Извлекает данные о поставщиках из JSON-файла и возвращает список словарей с соответствующей информацией.""" - pass + with open(json_file, 'r') as file: + data_json = json.load(file) + return data_json def insert_suppliers_data(cur, suppliers: list[dict]) -> None: """Добавляет данные из suppliers в таблицу suppliers.""" - pass + for sups in suppliers: + cur.execute(""" + INSERT INTO suppliers (company_name, contact, address, phone, fax, homepage) + VALUES (%s, %s, %s, %s, %s, %s) + """, + (sups.get('company_name'), sups.get('contact'), sups.get('address'), sups.get('phone'), + sups.get('fax'), sups.get('homepage')) + ) def add_foreign_keys(cur, json_file) -> None: """Добавляет foreign key со ссылкой на supplier_id в таблицу products.""" - pass + with open(json_file, 'r') as f: + data_suppliers = json.load(f) + for supplier in data_suppliers: + if products.product_name in [prod for prod in supplier.get('product')]: + cur.execute(""" + ALTER TABLE products ADD CONSTRAINT fk_products_suppliers FOREIGN KEY (product_name) REFERENCES suppliers(suppliers_id) + WHERE suppliers.company_name= + """) if __name__ == '__main__': diff --git a/poetry.lock b/poetry.lock new file mode 100644 index 000000000..55594d284 --- /dev/null +++ b/poetry.lock @@ -0,0 +1,28 @@ +# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. + +[[package]] +name = "psycopg2" +version = "2.9.9" +description = "psycopg2 - Python-PostgreSQL Database Adapter" +optional = false +python-versions = ">=3.7" +files = [ + {file = "psycopg2-2.9.9-cp310-cp310-win32.whl", hash = "sha256:38a8dcc6856f569068b47de286b472b7c473ac7977243593a288ebce0dc89516"}, + {file = "psycopg2-2.9.9-cp310-cp310-win_amd64.whl", hash = "sha256:426f9f29bde126913a20a96ff8ce7d73fd8a216cfb323b1f04da402d452853c3"}, + {file = "psycopg2-2.9.9-cp311-cp311-win32.whl", hash = "sha256:ade01303ccf7ae12c356a5e10911c9e1c51136003a9a1d92f7aa9d010fb98372"}, + {file = "psycopg2-2.9.9-cp311-cp311-win_amd64.whl", hash = "sha256:121081ea2e76729acfb0673ff33755e8703d45e926e416cb59bae3a86c6a4981"}, + {file = "psycopg2-2.9.9-cp312-cp312-win32.whl", hash = "sha256:d735786acc7dd25815e89cc4ad529a43af779db2e25aa7c626de864127e5a024"}, + {file = "psycopg2-2.9.9-cp312-cp312-win_amd64.whl", hash = "sha256:a7653d00b732afb6fc597e29c50ad28087dcb4fbfb28e86092277a559ae4e693"}, + {file = "psycopg2-2.9.9-cp37-cp37m-win32.whl", hash = "sha256:5e0d98cade4f0e0304d7d6f25bbfbc5bd186e07b38eac65379309c4ca3193efa"}, + {file = "psycopg2-2.9.9-cp37-cp37m-win_amd64.whl", hash = "sha256:7e2dacf8b009a1c1e843b5213a87f7c544b2b042476ed7755be813eaf4e8347a"}, + {file = "psycopg2-2.9.9-cp38-cp38-win32.whl", hash = "sha256:ff432630e510709564c01dafdbe996cb552e0b9f3f065eb89bdce5bd31fabf4c"}, + {file = "psycopg2-2.9.9-cp38-cp38-win_amd64.whl", hash = "sha256:bac58c024c9922c23550af2a581998624d6e02350f4ae9c5f0bc642c633a2d5e"}, + {file = "psycopg2-2.9.9-cp39-cp39-win32.whl", hash = "sha256:c92811b2d4c9b6ea0285942b2e7cac98a59e166d59c588fe5cfe1eda58e72d59"}, + {file = "psycopg2-2.9.9-cp39-cp39-win_amd64.whl", hash = "sha256:de80739447af31525feddeb8effd640782cf5998e1a4e9192ebdf829717e3913"}, + {file = "psycopg2-2.9.9.tar.gz", hash = "sha256:d1454bde93fb1e224166811694d600e746430c006fbb031ea06ecc2ea41bf156"}, +] + +[metadata] +lock-version = "2.0" +python-versions = "^3.12" +content-hash = "737e973ba72f4decd4d79fea552a7dcb2ec3e8e9d9eabebabf83ede597265a44" diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 000000000..269a88cfd --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,15 @@ +[tool.poetry] +name = "postgres-homeworks" +version = "0.1.0" +description = "" +authors = ["Your Name "] +readme = "README.md" + +[tool.poetry.dependencies] +python = "^3.12" +psycopg2 = "^2.9.9" + + +[build-system] +requires = ["poetry-core"] +build-backend = "poetry.core.masonry.api"