Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
23
Добавлен:
03.06.2024
Размер:
2.14 Mб
Скачать
  1. Анализ сущностей и связей между ними

Была создана ER-модель данной базы данных. Модель сущностных отношений (ER Modeling) – это графический подход к проектированию базы данных. Это модель данных высокого уровня, которая определяет элементы данных и их взаимосвязь для определенной программной системы.

В ER-модели связи делятся на три типа по множественности:

  • один-к-одному;

  • один-ко-многим;

  • многие-ко-многим.

Связь «один-к-одному» означает, что экземпляр одной сущности связан только с одним экземпляром другой сущности.

Связь «один-ко-многим» означает, что один экземпляр сущности, расположенный слева по связи, может быть связан с несколькими экземплярами сущности, расположенными справа по связи.

Связь «многие-ко-многим» означает, что один экземпляр первой сущности может быть связан с несколькими экземплярами второй сущности, и наоборот, один экземпляр второй сущности может быть связан с несколькими экземплярами первой сущности.

ER-модель созданной базы данных представлена на рисунке 1.

Рисунок 1 – ER-диаграмма базы данных

Скриншоты всех заполненных таблиц представлены в приложении А.

Код для создания базы данных представлен в приложении Б.

  1. Составление запросов к базе данных и их инкапсуляция

После создания и заполнения базы данных были составлены запросы, используемые для извлечения необходимых данных из таблицы. Все запросы были инкапсулированы в хранимые процедуры MySQL.

Запрос 1. Суммарная продолжительность показа ролика определенного рекламодателя:

Алгоритм выполнения:

  • Объединение таблиц customers, deals, advertisements и подзапроса, получающего количество показов каждого рекламного ролика из таблицы display_schedule.

  • Выборка данных по указанному клиенту (customer_id).

  • Расчет общей продолжительности рекламных роликов как сумма произведений количества показов рекламного ролика (count) на его продолжительность (duration_minutes).

  • Группировка результатов по имени клиента (customer_name).

Код процедуры представлен в Листинге 1.

Результаты выполнения представлены на рисунках 2, 3.

Скриншоты использованных таблиц представлены на рисунках 4 – 7.

Листинг 1 – Процедура запроса 1

DELIMITER $$

CREATE PROCEDURE get_total_ad_duration_by_customer(IN p_customer_id INT)

BEGIN

IF p_customer_id IS NULL OR p_customer_id <= 0 THEN

SIGNAL SQLSTATE '45000'

SET MESSAGE_TEXT = 'ID должен быть целым неотрицательным числом';

ELSE

SELECT

c.customer_name,

SUM(ds.count * a.duration_minutes) AS total_duration_minutes

FROM

customers c

JOIN deals d ON c.customer_id = d.customer_id

JOIN advertisements a ON d.ad_id = a.ad_id

JOIN (

SELECT

ad_id,

COUNT(*) AS count

FROM

display_schedule

GROUP BY

ad_id

) ds ON a.ad_id = ds.ad_id

WHERE

c.customer_id = p_customer_id

GROUP BY

c.customer_name;

END IF;

END$$

DELIMITER ;

Рисунок 2 – Результат вызова процедуры запроса 1

Рисунок 3 – Результат выполнения запроса 1 с некорректным параметром

Рисунок 4 - Таблица customers

Рисунок 5 – Таблица deals

Рисунок 6 – Таблица advertisements

Рисунок 7 - Таблица display_schedule

Запрос 2. Фамилии агентов, которые смогли привлечь трех наиболее выгодных рекламному агентству заказчиков:

Алгоритм выполнения:

  • Внутренний подзапрос рассчитывает общую стоимость сделок для каждого клиента (total_value), умножая продолжительность рекламы на стоимость минуты показа.

  • Использует GROUP BY для группировки данных по customer_id.

  • Сортирует данные по total_value в порядке убывания и ограничивает результат первыми тремя клиентами с наибольшей стоимостью сделок с помощью LIMIT 3.

  • Основной запрос: соединяет таблицы deals, agents, и customers с результатами подзапроса, чтобы извлечь имена агентов, клиентов и общую стоимость сделок клиентов.

  • Использует повторное соединение для получения total_value из подзапроса.

Код процедуры представлен в Листинге 2.

Результаты выполнения представлены на рисунке 8.

Скриншоты использованных таблиц представлены на рисунках 9 – 14.

Листинг 2 – Процедура запроса 2

DELIMITER $$

CREATE PROCEDURE get_agents_top_customers()

BEGIN

-- Выбираем топ-3 клиентов по общей стоимости сделок

SELECT

a.agent_name, -- Имя агента

c.customer_name, -- Имя клиента

cds.total_value -- Общая стоимость сделок клиента

FROM

(SELECT

customer_id,

SUM(a.duration_minutes * s.cost_per_minute) AS total_value -- Вычисление общей стоимости сделок клиента

FROM

deals d

JOIN advertisements a ON d.ad_id = a.ad_id

JOIN display_schedule ds ON a.ad_id = ds.ad_id

JOIN shows s ON ds.show_id = s.show_id

GROUP BY

customer_id

ORDER BY

total_value DESC

LIMIT 3

) AS top_customers

JOIN deals d ON top_customers.customer_id = d.customer_id

JOIN agents a ON d.agent_id = a.agent_id -- Соединение с таблицей агентов

JOIN customers c ON d.customer_id = c.customer_id -- Соединение с таблицей клиентов

JOIN (

SELECT

customer_id,

SUM(a.duration_minutes * s.cost_per_minute) AS total_value

FROM

deals d

JOIN advertisements a ON d.ad_id = a.ad_id

JOIN display_schedule ds ON a.ad_id = ds.ad_id

JOIN shows s ON ds.show_id = s.show_id

GROUP BY

customer_id

) AS cds ON cds.customer_id = c.customer_id;

END$$

DELIMITER ;

Рисунок 8 – Результат вызова процедуры запроса 2

Рисунок 9 – Таблица deals

Рисунок 10 – Таблица advertisements

Рисунок 11 - Таблица display_schedule

Рисунок 12 - Таблица shows

Рисунок 13 - Таблица customers

Рисунок 14 – Таблица agents

Запрос 3. Количество рекламных роликов, которые показывают каждый будний день с 13.00 до 17.00 часов:

Алгоритм выполнения:

  • Фильтрация данных по будним дням и временным интервалам: WEEKDAY(ds.display_date) BETWEEN 0 AND 4 выбирает только записи, относящиеся к будним дням (понедельник - пятница), TIME(ds.display_time) BETWEEN '13:00:00' AND '17:00:00' ограничивает выборку временным интервалом с 13:00 до 17:00.

  • Группировка и подсчет рекламных роликов: GROUP BY DAYNAME(ds.display_date) группирует данные по названиям будних дней, COUNT(*) AS advertisements_count подсчитывает количество рекламных роликов для каждого буднего дня.

  • Сортировка по порядку дней недели: ORDER BY FIELD(weekday, 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday') сортирует результаты в порядке дней недели, чтобы дни отображались от понедельника до пятницы.

Код процедуры представлен в Листинге 3.

Результаты выполнения представлены на рисунке 15.

Скриншоты использованных таблиц представлены на рисунках 16, 17.

Листинг 3 – Процедура запроса 3

DELIMITER $$

CREATE PROCEDURE get_ad_count_weekday()

BEGIN

-- Выбираем количество рекламных роликов по будним дням с 13:00 до 17:00

SELECT

DAYNAME(ds.display_date) AS weekday, -- Название буднего дня

COUNT(*) AS advertisements_count -- Количество рекламных роликов

FROM

display_schedule ds

JOIN shows s ON ds.show_id = s.show_id

WHERE

WEEKDAY(ds.display_date) BETWEEN 0 AND 4 -- Будние дни (понедельник - пятница)

AND TIME(ds.display_time) BETWEEN '13:00:00' AND '17:00:00' -- Временной интервал с 13:00 до 17:00

GROUP BY

weekday -- Группировка по будним дням

ORDER BY

FIELD(weekday, 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday'); -- Сортировка по порядку будних дней

END$$

DELIMITER ;

Рисунок 15 – Результат вызова процедуры запроса 3

Рисунок 16 - Таблица display_schedule

Рисунок 17 - Таблица shows

Запрос 4. Средняя зарплата агентов конкретной фирмы за последний год работы:

Алгоритм выполнения:

  • Объединяются таблицы deals, agents, customers, advertisements, display_schedule, и shows для получения полной информации о сделках, агентах, клиентах, рекламных роликах и показах.

  • WHERE c.customer_name = customer_name фильтрует записи по указанному имени клиента, передаваемому в качестве параметра процедуры.

  • AND d.deal_date BETWEEN DATE_SUB(NOW(), INTERVAL 1 YEAR) AND NOW() фильтрует записи по дате, выбирая сделки, совершенные за последний год.

  • ROUND(AVG(a.commission_rate * (s.cost_per_minute * ad.duration_minutes)), 2) AS avg_salary вычисляет среднюю зарплату агента. Зарплата рассчитывается как произведение комиссии агента на стоимость минуты рекламы и продолжительность рекламного ролика.

  • Используется функция AVG() для вычисления среднего значения зарплаты агента.

  • SELECT customer_name, avg_salary выводит имя клиента и среднюю зарплату агента за последний год, округленную до двух десятичных знаков

Код процедуры представлен в Листинге 4.

Результаты выполнения представлены на рисунке 18.

Скриншоты использованных таблиц представлены на рисунках 19 - 24.

Листинг 4 – Процедура запроса 4

DELIMITER $$

CREATE PROCEDURE get_avg_salary_for_customer_agent(IN customer_name VARCHAR(100))

BEGIN

-- Выбираем среднюю зарплату агента для указанного клиента за последний год

SELECT

customer_name,

ROUND(AVG(a.commission_rate * (s.cost_per_minute * ad.duration_minutes)), 2) AS avg_salary

FROM

deals d

JOIN agents a ON d.agent_id = a.agent_id

JOIN customers c ON d.customer_id = c.customer_id

JOIN advertisements ad ON d.ad_id = ad.ad_id

JOIN display_schedule ds ON ad.ad_id = ds.ad_id

JOIN shows s ON ds.show_id = s.show_id

WHERE

c.customer_name = customer_name -- Имя клиента передается как параметр

AND d.deal_date BETWEEN DATE_SUB(NOW(), INTERVAL 1 YEAR) AND NOW(); -- Выбираем сделки за последний год

END$$

DELIMITER ;

Рисунок 18 – Результат вызова процедуры запроса 4

Рисунок 19 – Таблица deals

Рисунок 20 – Таблица agents

Рисунок 21 – Таблица customers

Рисунок 22 – Таблица advertisements

Рисунок 23 – Таблица display_schedule

Рисунок 24 – Таблица shows

Запрос 5. Количество компаний–заказчиков, которые смогли оплатить показ в самых рейтинговых программах за последние 3 месяца:

Алгоритм выполнения:

  • Объединяются таблицы display_schedule, shows, и deals для получения информации о показах рекламы, шоу и сделках.

  • WHERE ds.display_date BETWEEN DATE_SUB(NOW(), INTERVAL 3 MONTH) AND NOW() фильтрует записи, выбирая данные за последние 3 месяца.

  • GROUP BY s.show_name, s.rating группирует данные по названию шоу и его рейтингу.

  • COUNT(DISTINCT d.customer_id) AS customer_count подсчитывает количество уникальных клиентов, которые заключили сделки для каждого шоу.

  • ORDER BY s.rating DESC сортирует результаты по убыванию рейтинга шоу.

  • LIMIT 10 ограничивает количество возвращаемых записей до 10.

Код процедуры представлен в Листинге 5.

Результаты выполнения представлены на рисунке 25.

Скриншоты использованных таблиц представлены на рисунках 26 - 28.

Листинг 5 – Процедура запроса 5

DELIMITER $$

CREATE PROCEDURE get_avg_salary_for_customer_agent(IN customer_name VARCHAR(100))

BEGIN

-- Выбираем среднюю зарплату агента для указанного клиента за последний год

SELECT

customer_name,

ROUND(AVG(a.commission_rate * (s.cost_per_minute * ad.duration_minutes)), 2) AS avg_salary

FROM

deals d

JOIN agents a ON d.agent_id = a.agent_id

JOIN customers c ON d.customer_id = c.customer_id

JOIN advertisements ad ON d.ad_id = ad.ad_id

JOIN display_schedule ds ON ad.ad_id = ds.ad_id

JOIN shows s ON ds.show_id = s.show_id

WHERE

c.customer_name = customer_name -- Имя клиента передается как параметр

AND d.deal_date BETWEEN DATE_SUB(NOW(), INTERVAL 1 YEAR) AND NOW(); -- Выбираем сделки за последний год

END$$

DELIMITER ;

Рисунок 25 – Результат вызова процедуры запроса 5

Рисунок 26 – Таблица display_schedule

Рисунок 27 – Таблица shows

Рисунок 28 – Таблица deals

Запрос 6. Контактное лицо от компании–заказчика, который заключил наибольшее количество договоров о рекламных кампаниях:

Алгоритм выполнения:

  • В подзапросе SELECT customer_id, COUNT(*) AS deal_count FROM deals GROUP BY customer_id ORDER BY deal_count DESC LIMIT 1, выполняется подсчет сделок для каждого клиента и выбирается клиент с наибольшим количеством сделок.

  • Результаты подзапроса объединяются с таблицей customers для получения информации о клиенте и его контактном лице.

  • Из объединенных данных выбираются имя контактного лица (c.contact_person), имя клиента (customer_name) и количество сделок (deal_count).

  • Запрос возвращает контактное лицо клиента, имя клиента и количество сделок для клиента, заключившего наибольшее количество сделок.

Код процедуры представлен в Листинге 6.

Результаты выполнения представлены на рисунке 29.

Скриншоты использованных таблиц представлены на рисунках 30, 31.

Листинг 6 – Процедура запроса 6

DELIMITER $$

CREATE PROCEDURE get_customer_with_most_deals()

BEGIN

-- Выбираем имя контактного лица клиента с наибольшим количеством сделок

SELECT

c.contact_person AS contact_name,

customer_name,

deal_count AS deal_count

-- Имя контактного лица

FROM

customers c

JOIN (

SELECT

customer_id,

COUNT(*) AS deal_count -- Количество сделок

FROM

deals

GROUP BY

customer_id

ORDER BY

deal_count DESC

LIMIT 1 -- Выбираем только одного клиента с наибольшим количеством сделок

) AS top_customer_deals ON c.customer_id = top_customer_deals.customer_id;

END$$

DELIMITER ;

Рисунок 29 – Результат вызова процедуры запроса 6

Рисунок 30 – Таблица deals

Рисунок 31 – Таблица customers

Запрос 7. Агент, совершивший минимальное количество сделок и при этом получивший наибольшие комиссионные:

Алгоритм выполнения:

  • В подзапросе выполняется подсчет сделок для каждого агента и вычисляется максимальная зарплата агента. Затем выбирается агент с минимальным количеством сделок и максимальной зарплатой.

  • Результаты подзапроса объединяются с таблицей agents для получения информации о самом удачливом агенте.

  • Из объединенных данных выбираются имя агента (a.agent_name), количество сделок (deal_count) и максимальная зарплата (max_salary).

  • Запрос возвращает имя агента, совершившего минимальное количество сделок и при этом получившего максимальную зарплату, количество его сделок и зарплату.

Код процедуры представлен в Листинге 7.

Результаты выполнения представлены на рисунке 32.

Скриншоты использованных таблиц представлены на рисунках 33 - 37.

Листинг 7 – Процедура запроса 7

DELIMITER $$

CREATE PROCEDURE get_luckiest_agent()

BEGIN

-- Выбираем имя самого удачливого агента

SELECT

a.agent_name AS lucky_agent,

deal_count,

max_salary

-- Имя агента

FROM

agents a

JOIN (

SELECT

d.agent_id,

COUNT(*) AS deal_count, -- Количество сделок

MAX(ROUND(a.commission_rate * (s.cost_per_minute * ad.duration_minutes), 2)) AS max_salary -- Максимальная зарплата

FROM

deals d

JOIN agents a ON d.agent_id = a.agent_id

JOIN advertisements ad ON d.ad_id = ad.ad_id

JOIN display_schedule ds ON ad.ad_id = ds.ad_id

JOIN shows s ON ds.show_id = s.show_id

GROUP BY

d.agent_id

ORDER BY

deal_count ASC, max_salary DESC

LIMIT 1 -- Выбираем только одного агента

) AS luckiest_agent_info ON a.agent_id = luckiest_agent_info.agent_id;

END$$

DELIMITER ;

Рисунок 32 – Результат вызова процедуры запроса 7

Рисунок 33 – Таблица deals

Рисунок 34 – Таблица agents

Рисунок 35 – Таблица advertisements

Рисунок 36 – Таблица display_schedule

Рисунок 37 – Таблица shows

Запрос 8. 5 рекламных агентств с наибольшим количеством заключенных договоров и суммарной выручкой за указанный промежуток времени:

Алгоритм выполнения:

  • В запросе выбираются данные о сделках и рекламе, связанные с агентами, за указанный промежуток времени (start_date до end_date). Для этого используются таблицы deals, advertisements, display_schedule и shows.

  • Полученные данные группируются по агентам (agent_id) с помощью GROUP BY.

  • Для каждого агента вычисляется количество заключенных сделок и суммарная выручка. Для этого используются функции COUNT() и SUM().

  • Результаты сортируются по убыванию количества сделок и суммарной выручки, чтобы определить топ-5 агентов с наибольшими показателями.

  • Затем используется LIMIT 5 для ограничения выборки только топ-5 агентами.

Код процедуры представлен в Листинге 8.

Результаты выполнения представлены на рисунках 38 - 43.

Скриншоты использованных таблиц представлены на рисунках .

Листинг 8 – Процедура запроса 8

DELIMITER $$

CREATE PROCEDURE get_top_agents_with_revenue(IN start_date DATE, IN end_date DATE)

BEGIN

-- Выбираем топ-5 агентов с наибольшим количеством заключенных договоров и суммарной выручкой за указанный промежуток времени

SELECT

a.agent_name, -- Имя агента

COUNT(d.deal_id) AS deal_count, -- Количество заключенных договоров

ROUND(SUM(a.commission_rate * (s.cost_per_minute * ad.duration_minutes))) AS total_revenue -- Суммарная выручка

FROM

agents a

LEFT JOIN deals d ON a.agent_id = d.agent_id

LEFT JOIN advertisements ad ON d.ad_id = ad.ad_id

LEFT JOIN display_schedule ds ON ad.ad_id = ds.ad_id

LEFT JOIN shows s ON ds.show_id = s.show_id

WHERE

d.deal_date BETWEEN start_date AND end_date -- Заданный промежуток времени

GROUP BY

a.agent_id

ORDER BY

deal_count DESC, total_revenue DESC -- Сортировка по количеству договоров и суммарной выручке

LIMIT 5; -- Ограничение до топ-5 агентов

END$$

DELIMITER ;

Рисунок 38 – Результат вызова процедуры запроса 8

Рисунок 39 – Таблица deals

Рисунок 40 – Таблица agents

Рисунок 41 – Таблица advertisements

Рисунок 42 – Таблица display_schedule

Рисунок 43 – Таблица shows

Запрос 9. Средняя продолжительность рекламы в передачах с рейтингом, выше указанного:

Алгоритм выполнения:

  • Выполняется запрос, который выбирает среднюю продолжительность рекламы (average_ad_duration) и количество рекламных роликов (ad_count) для передач с рейтингом выше указанного порога (rating_threshold). Для этого используются таблицы advertisements, display_schedule и shows, где рейтинг передачи выше порогового значения.

  • Результаты запроса содержат среднюю продолжительность рекламы и количество рекламных роликов для передач с высоким рейтингом.

Код процедуры представлен в Листинге 9.

Результаты выполнения представлены на рисунках 44, 45.

Скриншоты использованных таблиц представлены на рисунках 46 - 48.

Листинг 9 – Процедура запроса 9

DELIMITER $$

CREATE PROCEDURE get_ad_info_for_high_rating_shows(IN rating_threshold FLOAT)

BEGIN

IF rating_threshold > 10 OR rating_threshold < 0 OR rating_threshold IS NULL THEN

SIGNAL SQLSTATE '45000'

SET MESSAGE_TEXT = 'Введите рейтинг от 0 до 10';

ELSE

-- Вычисляем среднюю продолжительность и количество рекламы в передачах с рейтингом выше указанного

SELECT

ROUND(AVG(a.duration_minutes), 2) AS average_ad_duration, -- Средняя продолжительность рекламы

COUNT(*) AS ad_count -- Количество реклам

FROM

advertisements a

JOIN display_schedule ds ON a.ad_id = ds.ad_id

JOIN shows s ON ds.show_id = s.show_id

WHERE

s.rating > rating_threshold; -- Рейтинг выше указанного порога

END IF;

END$$

DELIMITER ;

Рисунок 44 – Результат вызова процедуры запроса 9

Рисунок 45 – Результат вызова процедуры запроса 9 с некорректным параметром

Рисунок 46 – Таблица advertisements

Рисунок 47 – Таблица display_schedule

Рисунок 48 – Таблица shows

Запрос 10. 5 передач, реклама в которых стоила больше всего денег за указанный промежуток времени:

Алгоритм выполнения:

  • Запрос выбирает информацию о шоу (show_name) и суммарную стоимость рекламы (total_revenue) для каждого шоу за указанный период времени. Используются таблицы display_schedule, shows и advertisements.

  • Выбираются записи из таблицы display_schedule, которые попадают в указанный временной диапазон start_date и end_date.

  • Данные группируются по идентификатору шоу (show_id), чтобы рассчитать суммарную стоимость рекламы для каждого шоу.

  • Результаты сортируются по убыванию суммарной стоимости рекламы, чтобы определить наиболее прибыльные шоу.

  • Выборка ограничивается пятью наиболее прибыльными шоу, используя оператор LIMIT 5.

Код процедуры представлен в Листинге 10.

Результаты выполнения представлены на рисунке 49.

Скриншоты использованных таблиц представлены на рисунках 50 - 52.

Листинг 10 – Процедура запроса 10

DELIMITER $$

CREATE PROCEDURE get_most_profitable_show(IN start_date DATE, IN end_date DATE)

BEGIN

-- Находим шоу, в котором реклама стоила больше всего за указанный период

SELECT

s.show_name, -- Название шоу

SUM(a.duration_minutes * s.cost_per_minute) AS total_revenue -- Суммарная стоимость рекламы

FROM

display_schedule ds

JOIN shows s ON ds.show_id = s.show_id

JOIN advertisements a ON ds.ad_id = a.ad_id

WHERE

ds.display_date BETWEEN start_date AND end_date -- Указанный период

GROUP BY

s.show_id

ORDER BY

total_revenue DESC

LIMIT 5; -- Выбираем только 5 шоу с максимальной суммарной стоимостью рекламы

END$$

DELIMITER ;

Рисунок 49 – Результат вызова процедуры запроса 10

Рисунок 50 – Таблица display_schedule

Рисунок 51 – Таблица shows

Рисунок 52 – Таблица advertisements