Проект представляет собой создание, наполнение и манипуляцию данными в БД MySQL. Целью проекта является закрепление полученных в курсе Базы данных знаний.
В проекте представлены 4 различные базы данных:
- транспортные средства;
- автомобильные гонки;
- бронирование отелей;
- структура организации.
Каждая из баз данных включает в себя этапы создания таблиц, наполнения их данными, а также решение задач разной сложности.
Каждая из представленных баз данных сопровождается скриптом, который создает таблицы базы данных и заполняет их тестовыми данными.
Структура базы данных включает три таблицы для хранения информации о различных типах транспортных средств: Vehicle, Car, Motorcycle и Bicycle. Каждая таблица имеет свои уникальные атрибуты и взаимосвязи.
- Цель: Содержит общую информацию о производителях и моделях транспортных средств.
- Поля:
maker: (VARCHAR) Название производителя автомобиля или мотоцикла.model: (VARCHAR) Название модели. Это поле также служит первичным ключом, что означает, что каждая модель должна быть уникальной.type: (ENUM) Тип транспортного средства, который может принимать одно из значений: 'Car', 'Motorcycle', 'Bicycle'.
- Цель: Содержит детали о легковых автомобилях.
- Поля:
vin: (VARCHAR) Уникальный идентификатор автомобиля (номер VIN), который является первичным ключом.model: (VARCHAR) Название модели автомобиля, которая ссылается на полеmodelв таблицеVehicle. Это поле используется как внешний ключ для обеспечения целостности данных.engine_capacity: (DECIMAL) Объем двигателя в литрах.horsepower: (INT) Мощность двигателя в лошадиных силах.price: (DECIMAL) Цена автомобиля в долларах.transmission: (ENUM) Тип трансмиссии, которая может быть 'Automatic' (автоматическая) или 'Manual' (механическая).
- Цель: Содержит детали о мотоциклах.
- Поля:
vin: (VARCHAR) Уникальный идентификатор мотоцикла (номер VIN), который является первичным ключом.model: (VARCHAR) Название модели мотоцикла, которая ссылается на полеmodelв таблицеVehicle, используется как внешний ключ.engine_capacity: (DECIMAL) Объем двигателя в литрах.horsepower: (INT) Мощность двигателя в лошадиных силах.price: (DECIMAL) Цена мотоцикла в долларах.type: (ENUM) Тип мотоцикла, который может принимать одно из значений: 'Sport', 'Cruiser', 'Touring'.
- Цель: Содержит детали о велосипедах.
- Поля:
serial_number: (VARCHAR) Уникальный серийный номер велосипеда, который является первичным ключом.model: (VARCHAR) Название модели велосипеда, которая ссылается на полеmodelв таблицеVehicle, используется как внешний ключ.gear_count: (INT) Количество передач велосипеда.price: (DECIMAL) Цена велосипеда в долларах.type: (ENUM) Тип велосипеда, который может принимать одно из значений: 'Mountain', 'Road', 'Hybrid'.
- Каждая из таблиц
Car,MotorcycleиBicycleссылается на таблицуVehicleчерез полеmodel, что обеспечивает целостность данных. Это значит, что каждая модель, указанная в таблицахCar,MotorcycleиBicycle, должна предварительно существовать в таблицеVehicle. - Таблицы
Car,MotorcycleиBicycleможно считать подмножествами таблицыVehicle, где каждая подтаблица содержит специфические детали для каждого типа транспортного средства.
Данная структура базы данных организует информацию о транспортных средствах в соответствии с их типами и основными характеристиками. Она позволяет удобно хранить, просматривать и поддерживать данные о различных моделях автомобилей, мотоциклов и велосипедов, сохраняя при этом их связь с производителями.
- Создадим БД vehicles в графическом интерфейсе.
- Создадим таблицы, запустив скрипт из файла databases/vehicles/V1__create_tables.sql.
- Наполним таблицы данными с помощью скрипта databases/vehicles/V2__insert_data.sql.
Условие: Найдите производителей (maker) и модели всех мотоциклов, которые имеют мощность более 150 лошадиных сил, стоят менее 20 тысяч долларов и являются спортивными (тип Sport). Также отсортируйте результаты по мощности в порядке убывания.
Решение: размещено в скрипте databases/vehicles/V3__task1.sql.
Условие: Найти информацию о производителях и моделях различных типов транспортных средств (автомобили, мотоциклы и велосипеды), которые соответствуют заданным критериям.
Автомобили: Извлечь данные о всех автомобилях, которые имеют:
Мощность двигателя более 150 лошадиных сил. Объем двигателя менее 3 литров. Цену менее 35 тысяч долларов. В выводе должны быть указаны производитель (maker), номер модели (model), мощность (horsepower), объем двигателя (engine_capacity) и тип транспортного средства, который будет обозначен как Car.
Мотоциклы: Извлечь данные о всех мотоциклах, которые имеют:
Мощность двигателя более 150 лошадиных сил. Объем двигателя менее 1,5 литров. Цену менее 20 тысяч долларов. В выводе должны быть указаны производитель (maker), номер модели (model), мощность (horsepower), объем двигателя (engine_capacity) и тип транспортного средства, который будет обозначен как Motorcycle.
Велосипеды: Извлечь данные обо всех велосипедах, которые имеют:
Количество передач больше 18. Цену менее 4 тысяч долларов. В выводе должны быть указаны производитель (maker), номер модели (model), а также NULL для мощности и объема двигателя, так как эти характеристики не применимы для велосипедов. Тип транспортного средства будет обозначен как Bicycle.
Сортировка: Результаты должны быть объединены в один набор данных и отсортированы по мощности в порядке убывания. Для велосипедов, у которых нет значения мощности, они будут располагаться внизу списка.
Решение: размещено в скрипте databases/vehicles/V4__task2.sql.
Структура базы данных включает в себя четыре основные таблицы, которые организуют информацию о классе автомобилей, самих автомобилях, гонках и результатах гонок. Рассмотрим каждую из таблиц детальнее:
- Цель: Хранит информацию о различных классах автомобилей.
- Поля:
class: (VARCHAR) Название класса автомобилей, который служит первичным ключом и должен быть уникальным для каждого класса.type: (ENUM) Тип класса, который может принимать значения 'Racing' или 'Street', определяющие назначения автомобилей.country: (VARCHAR) Страна, с которой связан этот класс автомобилей.numDoors: (INT) Количество дверей в автомобиле данного класса.engineSize: (DECIMAL) Размер двигателя в литрах, с точностью до одного знака после запятой.weight: (INT) Вес автомобиля в килограммах.
- Цель: Хранит информацию об автомобилях.
- Поля:
name: (VARCHAR) Название автомобиля, которое служит первичным ключом и должно быть уникальным.class: (VARCHAR) Название класса, к которому принадлежит автомобиль. Это поле используется как внешний ключ, ссылающийся на полеclassв таблицеClasses. Это обеспечивает целостность данных, гарантируя, что каждый автомобиль относится к существующему классу.
- Цель: Хранит информацию о гонках.
- Поля:
name: (VARCHAR) Название гонки, которое служит первичным ключом и должно быть уникальным.date: (DATE) Дата проведения гонки, что позволяет сохранить информацию о времени гонки.
- Цель: Хранит результаты гонок для автомобилей.
- Поля:
car: (VARCHAR) Название автомобиля, который участвовал в гонке. Это поле используется как внешний ключ, ссылающийся на полеnameв таблицеCars.race: (VARCHAR) Название гонки, в которой участвовал автомобиль. Это поле используется как внешний ключ, ссылающийся на полеnameв таблицеRaces.position: (INT) Позиция, которую автомобиль занял в гонке. Это число указывает на успешность участия автомобиля в конкретной гонке.- Пара (car, race) образует первичный ключ, гарантируя уникальность каждой записи в таблице результатов, так как один автомобиль не может участвовать в одной гонке более одного раза.
- Таблица
Carsссылается на таблицуClasses, обеспечивая связку между автомобилями и их классами. - Таблица
Resultsсвязывает автомобили с гонками, предоставляя информацию о том, какое место занял каждый автомобиль в конкретной гонке. Ссылки на таблицыCarsиRacesобеспечивают целостность и согласованность данных.
Данная структура базы данных организует и систематизирует информацию о классах автомобилей, самих автомобилях, гонках и их результатах. Она позволяет удобно хранить и обрабатывать данные о гоночных классах, автомобилях и их участии в гонках, сохраняя при этом целостность и связь между записями.
- Создадим БД car_races в графическом интерфейсе.
- Создадим таблицы, запустив скрипт из файла databases/car_races/V1__create_tables.sql.
- Наполним таблицы данными с помощью скрипта databases/car_races/V2__insert_data.sql.
Условие: Определить, какие автомобили из каждого класса имеют наименьшую среднюю позицию в гонках, и вывести информацию о каждом таком автомобиле для данного класса, включая его класс, среднюю позицию и количество гонок, в которых он участвовал. Также отсортировать результаты по средней позиции.
Решение: размещено в скрипте databases/car_races/V3__task1.sql.
Условие: Определить автомобиль, который имеет наименьшую среднюю позицию в гонках среди всех автомобилей, и вывести информацию об этом автомобиле, включая его класс, среднюю позицию, количество гонок, в которых он участвовал, и страну производства класса автомобиля. Если несколько автомобилей имеют одинаковую наименьшую среднюю позицию, выбрать один из них по алфавиту (по имени автомобиля).
Решение: размещено в скрипте databases/car_races/V4__task2.sql.
Условие: Определить классы автомобилей, которые имеют наименьшую среднюю позицию в гонках, и вывести информацию о каждом автомобиле из этих классов, включая его имя, среднюю позицию, количество гонок, в которых он участвовал, страну производства класса автомобиля, а также общее количество гонок, в которых участвовали автомобили этих классов. Если несколько классов имеют одинаковую среднюю позицию, выбрать все из них.
Решение: размещено в скрипте databases/car_races/V5__task3.sql.
Условие: Определить, какие автомобили имеют среднюю позицию лучше (меньше) средней позиции всех автомобилей в своем классе (то есть автомобилей в классе должно быть минимум два, чтобы выбрать один из них). Вывести информацию об этих автомобилях, включая их имя, класс, среднюю позицию, количество гонок, в которых они участвовали, и страну производства класса автомобиля. Также отсортировать результаты по классу и затем по средней позиции в порядке возрастания.
Решение: размещено в скрипте databases/car_races/V6__task4.sql.
Условие: Определить, какие классы автомобилей имеют наибольшее количество автомобилей с низкой средней позицией (больше 3.0) и вывести информацию о каждом автомобиле из этих классов, включая его имя, класс, среднюю позицию, количество гонок, в которых он участвовал, страну производства класса автомобиля, а также общее количество гонок для каждого класса. Отсортировать результаты по количеству автомобилей с низкой средней позицией.
Решение: размещено в скрипте databases/car_races/V7__task5.sql.
Структура базы данных предназначена для управления информацией о гостиницах, номерах, клиентах и бронированиях. Она состоит из четырех таблиц: Hotel, Room, Customer и Booking. Рассмотрим каждую таблицу подробнее.
- Цель: Хранит информацию о гостиницах.
- Поля:
ID_hotel: (INT) Уникальный идентификатор гостиницы, который служит первичным ключом. Этот идентификатор должен быть уникальным для каждой записи в таблице.name: (VARCHAR) Название гостиницы. Это обязательное поле, которое не может быть пустым.location: (VARCHAR) Местоположение гостиницы. Это также обязательное поле, не допускающее пустых значений.
- Цель: Хранит информацию о номерах в гостиницах.
- Поля:
ID_room: (INT) Уникальный идентификатор номера, который служит первичным ключом и должен быть уникальным для каждого номера.ID_hotel: (INT) Идентификатор гостиницы, к которой принадлежит номер. Это поле используется как внешний ключ, ссылающийся наID_hotelв таблицеHotel, что обеспечивает связь между номерами и гостиницами.room_type: (ENUM) Тип номера, который может принимать значения 'Single', 'Double' или 'Suite', указывая на тип размещения.price: (DECIMAL) Цена номера за ночь, представлена с точностью до двух знаков после запятой.capacity: (INT) Вместимость номера, то есть максимальное количество людей, которые могут разместиться в данном номере.
- Цель: Хранит информацию о клиентах гостиницы.
- Поля:
ID_customer: (INT) Уникальный идентификатор клиента, который служит первичным ключом. Этот идентификатор должен быть уникальным.name: (VARCHAR) Имя клиента. Это обязательное поле, которое не может быть пустым.email: (VARCHAR) Электронная почта клиента. Это обязательное поле, и его значения должны быть уникальными, чтобы избежать дубликатов. Оно не может быть пустым.phone: (VARCHAR) Номер телефона клиента. Это обязательное поле, не допускающее пустых значений.
- Цель: Хранит информацию о бронированиях.
- Поля:
ID_booking: (INT) Уникальный идентификатор бронирования, который служит первичным ключом.ID_room: (INT) Идентификатор номера, который забронирован. Это поле используется как внешний ключ, ссылающийся наID_roomв таблицеRoom, что обеспечивает связь между бронированиями и номерами.ID_customer: (INT) Идентификатор клиента, который сделал бронирование. Это поле используется как внешний ключ, ссылающийся наID_customerв таблицеCustomer, которым мы обеспечиваем связь между бронированиями и клиентами.check_in_date: (DATE) Дата заезда, указывающая, когда клиент планирует заехать в номер. Это обязательное поле.check_out_date: (DATE) Дата выезда, указывающая, когда клиент планирует покинуть номер. Это обязательное поле.
- Таблица
Roomссылается на таблицуHotel, обеспечивая связь между номерами и соответствующими гостиницами. - Таблица
Bookingсвязывает номера и клиентов, обеспечивая информацию о том, какие номера были забронированы конкретными клиентами. - Использование внешних ключей (в
RoomиBooking) поддерживает целостность данных, гарантируя, что все ссылки на гостиницы, номера и клиентов верны.
Данная структура базы данных эффективно организует и систематизирует информацию о гостиницах, номерах, клиентах и их бронированиях. Это позволяет удобно управлять данными, обеспечивая целостность информации и легкость доступа к различным аспектам гостиничного сервиса.
- Создадим БД hotels_booking в графическом интерфейсе.
- Создадим таблицы, запустив скрипт из файла databases/hotels_booking/V1__create_tables.sql.
- Наполним таблицы данными с помощью скрипта databases/hotels_booking/V2__insert_data.sql.
Условие: Определить, какие клиенты сделали более двух бронирований в разных отелях, и вывести информацию о каждом таком клиенте, включая его имя, электронную почту, телефон, общее количество бронирований, а также список отелей, в которых они бронировали номера (объединенные в одно поле через запятую с помощью CONCAT). Также подсчитать среднюю длительность их пребывания (в днях) по всем бронированиям. Отсортировать результаты по количеству бронирований в порядке убывания.
Решение: размещено в скрипте databases/hotels_booking/V3__task1.sql.
Условие: Необходимо провести анализ клиентов, которые сделали более двух бронирований в разных отелях и потратили более 500 долларов на свои бронирования. Для этого: Определить клиентов, которые сделали более двух бронирований и забронировали номера в более чем одном отеле. Вывести для каждого такого клиента следующие данные: ID_customer, имя, общее количество бронирований, общее количество уникальных отелей, в которых они бронировали номера, и общую сумму, потраченную на бронирования. Также определить клиентов, которые потратили более 500 долларов на бронирования, и вывести для них ID_customer, имя, общую сумму, потраченную на бронирования, и общее количество бронирований. В результате объединить данные из первых двух пунктов, чтобы получить список клиентов, которые соответствуют условиям обоих запросов. Отобразить поля: ID_customer, имя, общее количество бронирований, общую сумму, потраченную на бронирования, и общее количество уникальных отелей. Результаты отсортировать по общей сумме, потраченной клиентами, в порядке убывания.
Решение: размещено в скрипте databases/hotels_booking/V4__task2.sql.
Условие: Вам необходимо провести анализ данных о бронированиях в отелях и определить предпочтения клиентов по типу отелей. Для этого выполните следующие шаги:
Категоризация отелей. Определите категорию каждого отеля на основе средней стоимости номера:
«Дешевый»: средняя стоимость менее 175 долларов. «Средний»: средняя стоимость от 175 до 300 долларов. «Дорогой»: средняя стоимость более 300 долларов. Анализ предпочтений клиентов. Для каждого клиента определите предпочитаемый тип отеля на основе количества отелей в каждой категории, которые они посетили. Если у клиента одинаковое количество отелей в нескольких категориях, выбирайте самую дорогую категорию:
Если у клиента есть хотя бы один «дорогой» отель, присвойте ему категорию «дорогой». Если у клиента нет «дорогих» отелей, но есть хотя бы один «средний», присвойте ему категорию «средний». Если у клиента нет «дорогих» и «средних» отелей, но есть «дешевые», присвойте ему категорию предпочитаемых отелей «дешевый». Вывод информации. Выведите для каждого клиента следующую информацию:
ID_customer: уникальный идентификатор клиента. name: имя клиента. preferred_hotel_type: предпочитаемый тип отеля. visited_hotels: список уникальных отелей, которые посетил клиент. Сортировка результатов. Отсортируйте клиентов так, чтобы сначала шли клиенты с «дешевыми» отелями, затем со «средними» и в конце — с «дорогими».
Решение: размещено в скрипте databases/hotels_booking/V5__task3.sql.
Структура базы данных предназначена для управления информацией о сотрудниках, их ролях, департаментах, проектах и задачах. Она состоит из пяти таблиц: Departments, Roles, Employees, Projects и Tasks. Рассмотрим каждую таблицу подробнее.
- Цель: Хранит информацию о департаментах в организации.
- Поля:
DepartmentID: (INT) Уникальный идентификатор департамента, который является первичным ключом. Этот идентификатор должен быть уникальным для каждой записи.DepartmentName: (VARCHAR) Название департамента. Это обязательное поле (NOT NULL), которое не может быть пустым.
- Цель: Хранит информацию о ролях сотрудников внутри организации.
- Поля:
RoleID: (INT) Уникальный идентификатор роли, который служит первичным ключом. Этот идентификатор должен быть уникальным.RoleName: (VARCHAR) Название роли. Это также обязательное поле (NOT NULL), не допускающее пустых значений.
- Цель: Хранит информацию о сотрудниках организации.
- Поля:
EmployeeID: (INT) Уникальный идентификатор сотрудника, который является первичным ключом. Этот идентификатор должен быть уникальным для каждого сотрудника.Name: (VARCHAR) Имя сотрудника. Это обязательное поле (NOT NULL), которое не может быть пустым.Position: (VARCHAR) Должность сотрудника. Это поле может быть пустым.ManagerID: (INT) Идентификатор менеджера, который также является сотрудником. Это поле используется как внешний ключ, ссылающийся наEmployeeIDв той же таблицеEmployees, что позволяет создать иерархию менеджеров и подчиненных.DepartmentID: (INT) Идентификатор департамента, к которому принадлежит сотрудник. Это поле используется как внешний ключ, ссылающийся наDepartmentIDв таблицеDepartments.RoleID: (INT) Идентификатор роли, которая соответствует сотруднику. Это поле используется как внешний ключ, ссылающийся наRoleIDв таблицеRoles.
- Цель: Хранит информацию о проектах организованными отделами.
- Поля:
ProjectID: (INT) Уникальный идентификатор проекта, который является первичным ключом. Этот идентификатор должен быть уникальным для каждого проекта.ProjectName: (VARCHAR) Название проекта. Это обязательное поле (NOT NULL), не допускающее пустых значений.StartDate: (DATE) Дата начала проекта. Это поле может быть пустым.EndDate: (DATE) Дата окончания проекта. Это поле может быть пустым.DepartmentID: (INT) Идентификатор департамента, который отвечает за проект. Это поле используется как внешний ключ, ссылающийся наDepartmentIDв таблицеDepartments.
- Цель: Хранит информацию о задачах, назначенных на сотрудников в рамках проектов.
- Поля:
TaskID: (INT) Уникальный идентификатор задачи, который служит первичным ключом. Этот идентификатор должен быть уникальным для каждой задачи.TaskName: (VARCHAR) Название задачи. Это обязательное поле (NOT NULL), не допускающее пустых значений.AssignedTo: (INT) Идентификатор сотрудника, которому назначена задача. Это поле используется как внешний ключ, ссылающийся наEmployeeIDв таблицеEmployees.ProjectID: (INT) Идентификатор проекта, к которому относится задача. Это поле используется как внешний ключ, ссылающийся наProjectIDв таблицеProjects.
- Таблицы
Employees,Projects, иTasksсвязаны между собой через внешние ключи, что позволяет интегрировать данные о сотрудниках, их задачах и проектах. ManagerIDвEmployeesпозволяет создать иерархическую структуру управления, связывая сотрудников с их менеджерами.DepartmentIDсвязываетEmployeesс соответствующими департаментами, а также проекты с организацией в рамках определенного департамента.RoleIDсвязывает сотрудников с их ролями, что позволяет классифицировать их функции внутри компании.
Данная структура базы данных обеспечивает четкое управление данными о департаментах, ролях сотрудников, их проектах и задачах. Это позволяет эффективно организовывать, отслеживать и управлять ресурсами и задачами в компании, что является ключевым для успешного функционирования и достижения бизнес-целей.
- Создадим БД company_structure в графическом интерфейсе.
- Создадим таблицы, запустив скрипт из файла databases/company_structure/V1__create_tables.sql.
- Наполним таблицы данными с помощью скрипта databases/company_structure/V2__insert_data.sql.
Условие: Найти всех сотрудников, подчиняющихся Ивану Иванову (с EmployeeID = 1), включая их подчиненных и подчиненных подчиненных. Для каждого сотрудника вывести следующую информацию:
EmployeeID: идентификатор сотрудника. Имя сотрудника. ManagerID: Идентификатор менеджера. Название отдела, к которому он принадлежит. Название роли, которую он занимает. Название проектов, к которым он относится (если есть, конкатенированные в одном столбце через запятую). Название задач, назначенных этому сотруднику (если есть, конкатенированные в одном столбце через запятую). Если у сотрудника нет назначенных проектов или задач, отобразить NULL. Требования: Рекурсивно извлечь всех подчиненных сотрудников Ивана Иванова и их подчиненных. Для каждого сотрудника отобразить информацию из всех таблиц. Результаты должны быть отсортированы по имени сотрудника. Решение задачи должно представлять из себя один sql-запрос и задействовать ключевое слово RECURSIVE.
Решение: размещено в скрипте databases/company_structure/V3__task1.sql.
Условие: Найти всех сотрудников, подчиняющихся Ивану Иванову с EmployeeID = 1, включая их подчиненных и подчиненных подчиненных. Для каждого сотрудника вывести следующую информацию:
EmployeeID: идентификатор сотрудника. Имя сотрудника. Идентификатор менеджера. Название отдела, к которому он принадлежит. Название роли, которую он занимает. Название проектов, к которым он относится (если есть, конкатенированные в одном столбце). Название задач, назначенных этому сотруднику (если есть, конкатенированные в одном столбце). Общее количество задач, назначенных этому сотруднику. Общее количество подчиненных у каждого сотрудника (не включая подчиненных их подчиненных). Если у сотрудника нет назначенных проектов или задач, отобразить NULL.
Решение: размещено в скрипте databases/company_structure/V4__task2.sql.
Условие: Найти всех сотрудников, которые занимают роль менеджера и имеют подчиненных (то есть число подчиненных больше 0). Для каждого такого сотрудника вывести следующую информацию:
EmployeeID: идентификатор сотрудника. Имя сотрудника. Идентификатор менеджера. Название отдела, к которому он принадлежит. Название роли, которую он занимает. Название проектов, к которым он относится (если есть, конкатенированные в одном столбце). Название задач, назначенных этому сотруднику (если есть, конкатенированные в одном столбце). Общее количество подчиненных у каждого сотрудника (включая их подчиненных). Если у сотрудника нет назначенных проектов или задач, отобразить NULL.
Решение: размещено в скрипте databases/company_structure/V5__task3.sql.